home *** CD-ROM | disk | FTP | other *** search
/ OpenGL Superbible (2nd Edition) / OpenGL SuperBible e2.iso / tools / Mesa-3.0 / SRC / S3 / S3mesa.c < prev    next >
Encoding:
C/C++ Source or Header  |  1997-11-13  |  76.2 KB  |  3,097 lines

  1. /* s3mesa.c - S3/Mesa interface */
  2.  
  3. /*
  4.  * This library is free software; you can redistribute it and/or
  5.  * modify it under the terms of the GNU Library General Public
  6.  * License as published by the Free Software Foundation; either
  7.  * version 2 of the License, or (at your option) any later version.
  8.  *
  9.  * This library is distributed in the hope that it will be useful,
  10.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  12.  * Library General Public License for more details.
  13.  *
  14.  * You should have received a copy of the GNU Library General Public
  15.  * License along with this library; if not, write to the Free
  16.  * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  17.  */
  18.  
  19.  
  20. /* This driver is written by S3 Inc. Contact rkoduri@s3.com with questions
  21.  * comments and bugs.
  22.  *
  23.  * The structure of this driver is based on the 3Dfx fxMesa driver by David
  24.  * Bucciarelli (with assistance from Henri Fousse, Jack Palevich, Diego Picciani,
  25.  * Brian Paul)
  26.  */
  27.  
  28. /* Bugs found in Mesa:
  29.  * Pointers being changed that aren't required
  30.  * Texture coordinate clipping is broken?
  31.  * A lot of the driver functions aren't checked for NULL
  32.  */
  33.  
  34. #ifdef S3
  35.  
  36.  
  37. #include <windows.h>  /* is this really needed? */
  38. #include <math.h>
  39. #include <stdio.h>
  40. #include <stdlib.h>
  41. #include "context.h"
  42. #include "macros.h"
  43. #include "matrix.h"
  44. #include "texture.h"
  45. #include "types.h"
  46. #include "vb.h"
  47. #include "xform.h"
  48. #include "s3mesa.h"
  49.  
  50.  
  51. #include <ddraw.h>
  52.  
  53.  
  54.  
  55. /* Different debug modes - any extra debug strings should go under one of these */
  56. //#define DEBUG_INIT                // Debug initialisation code
  57. //#define DEBUG_SURFACES            // Debug all DirectDraw and S3 surface data
  58. //#define DEBUG_PRIMITIVES        // Debug primitive data - VERY extensive!
  59. //#define DEBUG_TEXTURES            // Debug textures
  60. //#define DEBUG_STATE                // Debug all renderer state not involved in texturing
  61. //#define DEBUG_GL                // Debug GL interface
  62.  
  63.  
  64.  
  65.  
  66. LPDIRECTDRAW gpDD;
  67. S3DTK_LPFUNCTIONLIST s3f;
  68.  
  69. #define MAXNUM_TEX    512
  70.  
  71. #define PACKEDCOLOR(r,g,b,a) (( ((unsigned int)(a))<<24 )|( ((unsigned int)(b))<<16 )|( ((unsigned int)(g))<<8 )|(r))
  72.  
  73. #define FUNC_DEPTH    0x01
  74. #define FUNC_SMOOTH    0x02
  75. #define FUNC_TEX_DECAL    0x04
  76. #define FUNC_TEX_MOD    0x08
  77.  
  78.  
  79. /* Information stored internally about a texture */
  80. typedef struct {
  81.     int width, height;            // obvious I hope
  82.     int mipmaplevels;            // Number of mipmap levels in this texture
  83.     void *data;                    // Pointer to converted data
  84.     int size;                    // Texture size
  85.  
  86.     int transparent;            // Set if this texture needs transparency enabled
  87.     int have_mipmap;            // Set if have a mipmap for this texture
  88.  
  89.     LPDIRECTDRAWSURFACE vram_surface;    // Surface in texture cache
  90.     int on_card;                // Set if currently uploaded to card
  91.  
  92.     GLenum minfilter;            // Texture filtering
  93.     GLenum magfilter;
  94.     ULONG filter;                // S3DTK filtering code
  95.  
  96.     S3DTK_SURFACE s3_surface;    // S3 surface associated with this texture
  97. } texinfo;
  98.  
  99.  
  100. /*
  101.  * All the things needed for
  102.  */
  103. struct s3_mesa_context {
  104.     GLcontext *gl_ctx;             /* the core Mesa context */
  105.     GLvisual *gl_vis;              /* describes the color buffer */
  106.     GLframebuffer *gl_buffer;      /* the ancillary buffers */
  107.  
  108.     GLint width, height;           /* size of color buffer */
  109.     GLboolean double_buffer;
  110.  
  111.     HWND hwnd;
  112.     LPDIRECTDRAWSURFACE front_surface, back_surface, z_surface;
  113.     LPDIRECTDRAWCLIPPER clipper;
  114.     int fullscreen;
  115.     int screen_width, screen_height, window_width, window_height;
  116.     S3DTK_SURFACE s3_draw, s3_z;
  117.  
  118.     GLenum current_buffer;    // Current draw buffer
  119.  
  120.     dword color;
  121.     dword clearc;
  122.     dword cleara;
  123.  
  124.     /* Texture management */
  125.     texinfo ti[MAXNUM_TEX];
  126.     int currenttex;
  127.  
  128.     /* The texture cache: a list of which textures are currently in vram. */
  129.     int texture_cache[MAXNUM_TEX];    // the texObject number of this entry
  130.     int texture_cache_head;
  131.     int texture_cache_tail;
  132.  
  133.     float wscale, hither, yon;
  134.     float fog_start, fog_end;
  135.     float fog_const;                // Constant for calculating fog addresses
  136.  
  137.     ULONG vram_base;            // PHYSICAL address, in case things turn up in different spaces
  138.  
  139.     int renderdisabled;            // bitvector of all the different things that can block rendering
  140.  
  141.     /* Output vertices */
  142.     S3DTK_VERTEX_TEX vertex_tex[VB_SIZE];
  143. };
  144.  
  145. s3MesaContext Currents3MesaCtx=NULL;
  146. LPDIRECTDRAWSURFACE front_surface;
  147.  
  148. static void BuildDispatchTable(GLcontext *ctx);
  149. static void SetS3RenderState(GLcontext *ctx);
  150.  
  151.  
  152. int gamma_table[256];
  153.  
  154.  
  155.  
  156. /*
  157.  * Correct LinearToPhysical function - this works for both 95 and NT
  158.  */
  159. ULONG LinearToPhysical(ULONG linear)
  160. {
  161.     ULONG low12bits;
  162.     low12bits = linear & 0x00000fff;
  163.     return(S3DTK_LinearToPhysical(linear & 0xfffff000) + low12bits);
  164. }
  165.  
  166.  
  167.  
  168. /*
  169.  * The ViRGE usually has quite dark output. Adding this will
  170.  * prescale the textures on the way in, which helps a lot for Quake.
  171.  */
  172. void BuildGammaTable(void)
  173. {
  174.     int i;
  175.     float val;
  176. //    float gamma = 1 / 1.4;
  177.     float gamma = 1.0f;
  178.  
  179.     for(i=0;i<256;i++) {
  180.         val = ((float) i) / 255;
  181.         if (gamma != 1.0f)
  182.             val = pow(val, gamma);
  183.  
  184.         gamma_table[i] = (int) (255.0f*val);
  185.     }
  186.  
  187. }
  188.  
  189.  
  190.  
  191. void CleanExit(int n)
  192. {
  193.     if (s3f) {
  194.         S3DTK_DestroyRenderer(&s3f);
  195.         S3DTK_ExitLib();
  196.     }
  197.     if (gpDD)
  198.         IDirectDraw_Release(gpDD);
  199.     exit(n);
  200. }
  201.  
  202.  
  203.  
  204.  
  205.  
  206.  
  207.  
  208.  
  209.  
  210.  
  211.  
  212. /* DIRECT DRAW interface */
  213.  
  214.  
  215. /*
  216.  * Allocate the front and back buffers for fullscreen (EXCLUSIVE) operation
  217.  */
  218. HRESULT DDSetupFullscreenSurfaces(  LPDIRECTDRAWSURFACE *front_surface,
  219.                                     LPDIRECTDRAWSURFACE *back_surface)
  220. {
  221.     HRESULT result;
  222.     DDSURFACEDESC ddsd;
  223.     DDSCAPS ddsCaps;
  224.  
  225.     /* Create a primary surface with one back buffer */
  226.     memset(&ddsd, 0, sizeof(DDSURFACEDESC));
  227.     ddsd.dwSize = sizeof(DDSURFACEDESC);
  228.     ddsd.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT;
  229.     ddsd.ddsCaps.dwCaps = DDSCAPS_COMPLEX | DDSCAPS_PRIMARYSURFACE | DDSCAPS_FLIP | DDSCAPS_VIDEOMEMORY;
  230.     ddsd.dwBackBufferCount = 1;
  231.     if ((result = IDirectDraw_CreateSurface(gpDD, &ddsd, front_surface, NULL)) != DD_OK)
  232.         return(result);
  233.  
  234.     /* Pick up the back buffer */
  235.     memset(&ddsCaps, 0, sizeof(DDSCAPS));
  236.     ddsCaps.dwCaps = DDSCAPS_BACKBUFFER;
  237.     if (IDirectDrawSurface_GetAttachedSurface(*front_surface, &ddsCaps, back_surface) != DD_OK)
  238.         return(result);
  239.  
  240.     return(DD_OK);
  241. }
  242.  
  243.  
  244. /*
  245.  * Pick up the Windows primary surface for windowed mode
  246.  */
  247. HRESULT DDSetupPrimarySurface(LPDIRECTDRAWSURFACE *front_surface)
  248. {
  249.     HRESULT result;
  250.     DDSURFACEDESC ddsd;
  251.  
  252.     memset(&ddsd, 0, sizeof(DDSURFACEDESC));
  253.     ddsd.dwSize = sizeof(DDSURFACEDESC);
  254.     ddsd.dwFlags = DDSD_CAPS;
  255.     ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE | DDSCAPS_VIDEOMEMORY;
  256.     if ((result = IDirectDraw_CreateSurface(gpDD, &ddsd, front_surface, NULL)) != DD_OK)
  257.         return(result);
  258. }
  259.  
  260.  
  261. /*
  262.  * Allocate a back buffer
  263.  */
  264. HRESULT DDSetupBackSurface(LPDIRECTDRAWSURFACE *back_surface, int w, int h)
  265. {
  266.     HRESULT result;
  267.     DDSURFACEDESC ddsd;
  268.  
  269.     /* Create a back buffer */
  270.     memset(&ddsd, 0, sizeof(DDSURFACEDESC));
  271.     ddsd.dwSize = sizeof(DDSURFACEDESC);
  272.     ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
  273.     ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_VIDEOMEMORY;
  274.     ddsd.dwWidth = w;
  275.     ddsd.dwHeight = h;
  276.     if ((result = IDirectDraw_CreateSurface(gpDD, &ddsd, back_surface, NULL)) != DD_OK)
  277.         return(result);
  278.  
  279.     return(DD_OK);
  280. }
  281.  
  282.  
  283.  
  284.  
  285. /*
  286.  * Allocate a Z-buffer surface
  287.  *
  288.  * Recently modified to work on NT.
  289.  */
  290. HRESULT DDSetupZSurface(LPDIRECTDRAWSURFACE *surface, int w, int h)
  291. {
  292.     HRESULT result;
  293.     DDSURFACEDESC ddsd;
  294.  
  295.     /* Allocate a Z surface in video memory so the card can access it */
  296.     memset(&ddsd, 0, sizeof(DDSURFACEDESC));
  297.      ddsd.dwSize = sizeof(DDSURFACEDESC);
  298.  
  299. #if 0
  300.     /* Old method; this is what it _should_ be, but doesn't work on NT, because
  301.      * NT currently doesn't have Direct3D and so doesn't support Z-buffer allocation
  302.      * through DirectDraw */
  303.      ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_ZBUFFERBITDEPTH;
  304.      ddsd.ddsCaps.dwCaps = DDSCAPS_ZBUFFER | DDSCAPS_VIDEOMEMORY;
  305.     ddsd.dwZBufferBitDepth = 16;
  306. #else
  307.     /* This works on 95 and NT, although it looks a bit silly it doesn't matter as
  308.      * we're not using Direct3D */
  309.      ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
  310.      ddsd.ddsCaps.dwCaps = DDSCAPS_OVERLAY | DDSCAPS_VIDEOMEMORY;
  311.     ddsd.ddpfPixelFormat.dwRGBBitCount = 16;
  312.     ddsd.ddpfPixelFormat.dwFlags  = DDPF_RGB ; 
  313.     ddsd.ddpfPixelFormat.dwFourCC = BI_RGB ;
  314.     ddsd.ddpfPixelFormat.dwRBitMask = 0x7c00 ; 
  315.     ddsd.ddpfPixelFormat.dwGBitMask = 0x03e0; 
  316.     ddsd.ddpfPixelFormat.dwBBitMask = 0x001f ; 
  317. #endif
  318.  
  319.     ddsd.dwWidth = w;
  320.     ddsd.dwHeight = h;
  321.      if ((result = IDirectDraw_CreateSurface(gpDD, &ddsd, surface, NULL)) != DD_OK)
  322.         return(result);
  323.  
  324.     return(DD_OK);
  325. }
  326.  
  327.  
  328.  
  329. /*
  330.  * Set up a surface to be used as a texture
  331.  */
  332. HRESULT DDSetupTextureSurface(LPDIRECTDRAWSURFACE *surface, int w, int h, int s3format)
  333. {
  334.     HRESULT result;
  335.     DDSURFACEDESC ddsd;
  336.  
  337.     memset(&ddsd, 0, sizeof(DDSURFACEDESC));
  338.     ddsd.dwSize = sizeof(DDSURFACEDESC);
  339.     ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
  340.  
  341.  
  342.     /* This also works on 95 but not NT and again, doesn't matter because no D3D */
  343.     //ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_VIDEOMEMORY;
  344.     /* This works on both: NT doesn't allow pixelformat for anything but overlays, it seems */
  345.     ddsd.ddsCaps.dwCaps = DDSCAPS_OVERLAY | DDSCAPS_VIDEOMEMORY;
  346.  
  347.  
  348.     ddsd.dwWidth = w;
  349.     ddsd.dwHeight = h;
  350.     ddsd.ddpfPixelFormat.dwSize   = sizeof(DDPIXELFORMAT);
  351.     switch(s3format) {
  352.     case S3DTK_TEXARGB8888:
  353.         ddsd.ddpfPixelFormat.dwRGBBitCount = 32;
  354.         ddsd.ddpfPixelFormat.dwFlags  = DDPF_RGB ; 
  355.         ddsd.ddpfPixelFormat.dwFourCC = BI_RGB ;
  356.         ddsd.ddpfPixelFormat.dwRBitMask = 0x000000ff ; 
  357.         ddsd.ddpfPixelFormat.dwGBitMask = 0x0000ff00; 
  358.         ddsd.ddpfPixelFormat.dwBBitMask = 0x00ff0000 ; 
  359.         break;
  360.     case S3DTK_TEXARGB4444:
  361.         ddsd.ddpfPixelFormat.dwRGBBitCount = 16;
  362.         ddsd.ddpfPixelFormat.dwFlags  = DDPF_RGB ; 
  363.         ddsd.ddpfPixelFormat.dwFourCC = BI_RGB ;
  364. #if 0
  365.         /* If defined as an overlay, 444 is not a supported overlay format, so select one that is */
  366.         ddsd.ddpfPixelFormat.dwRBitMask = 0x0f00 ; 
  367.         ddsd.ddpfPixelFormat.dwGBitMask = 0x00f0; 
  368.         ddsd.ddpfPixelFormat.dwBBitMask = 0x000f ; 
  369. #else
  370.         /* Use 555 instead */
  371.         ddsd.ddpfPixelFormat.dwRBitMask = 0x7c00 ; 
  372.         ddsd.ddpfPixelFormat.dwGBitMask = 0x03e0; 
  373.         ddsd.ddpfPixelFormat.dwBBitMask = 0x001f ; 
  374. #endif
  375.         break;
  376.     case S3DTK_TEXARGB1555:
  377.         ddsd.ddpfPixelFormat.dwRGBBitCount = 16;
  378.         ddsd.ddpfPixelFormat.dwFlags  = DDPF_RGB ; 
  379.         ddsd.ddpfPixelFormat.dwFourCC = BI_RGB ;
  380.         ddsd.ddpfPixelFormat.dwRBitMask = 0x7c00 ; 
  381.         ddsd.ddpfPixelFormat.dwGBitMask = 0x03e0; 
  382.         ddsd.ddpfPixelFormat.dwBBitMask = 0x001f ; 
  383.         break;
  384.     default :
  385.         // Set a value that will cause the code to fail the createsurface
  386.         ddsd.ddpfPixelFormat.dwFlags = 0;
  387.         break;
  388.     }
  389.     if ((result = IDirectDraw_CreateSurface(gpDD, &ddsd, surface, NULL)) != DD_OK)
  390.         return(result);
  391.  
  392.     return(DD_OK);
  393. }
  394.  
  395.  
  396.  
  397. /*
  398.  * Lock and unlock
  399.  */
  400. HRESULT LockSurface(LPDIRECTDRAWSURFACE surface, void **addr, dword *pitch_bytes)
  401. {
  402.     HRESULT            result;
  403.     DDSURFACEDESC    surface_descriptor;
  404.  
  405.     /* Lock the surface, pick up the info */
  406.     memset(&surface_descriptor, 0, sizeof(surface_descriptor));
  407.     surface_descriptor.dwSize = sizeof(surface_descriptor);
  408.     result = IDirectDrawSurface_Lock(surface, NULL, &surface_descriptor,
  409.                                      DDLOCK_SURFACEMEMORYPTR | DDLOCK_WAIT, NULL);
  410.  
  411.     if (result == DDERR_SURFACELOST) {
  412.         result = IDirectDrawSurface_Restore(surface);
  413.         if (result != DD_OK)
  414.             return result;
  415.  
  416.         result = IDirectDrawSurface_Lock(surface, NULL, &surface_descriptor,
  417.                                          DDLOCK_SURFACEMEMORYPTR | DDLOCK_WAIT, NULL);
  418.     }
  419.  
  420.     if (result != DD_OK)
  421.         return result;
  422.  
  423.     if (addr) *addr = surface_descriptor.lpSurface;
  424.     if (pitch_bytes) *pitch_bytes = surface_descriptor.lPitch;
  425.  
  426.     return DD_OK;
  427. }
  428.  
  429. /*
  430.  * Unlock surface
  431.  */
  432. HRESULT UnlockSurface(LPDIRECTDRAWSURFACE surface, void *addr)
  433. {
  434.     HRESULT    result;
  435.  
  436.     if ((result = IDirectDrawSurface_Unlock(surface, addr)) != DD_OK)
  437.         return result;
  438.  
  439.     return DD_OK;
  440. }
  441.  
  442.  
  443. /*
  444.  * Get address of a surface
  445.  *
  446.  * Note that this is quite slow, because Lock and Unlock are expensive.
  447.  */
  448. HRESULT GetSurfaceAddress(LPDIRECTDRAWSURFACE surface, void **addr)
  449. {
  450.     HRESULT result;
  451.  
  452.     if ((result = LockSurface(surface, addr, NULL)) != DD_OK)
  453.         return(result);
  454.     return(UnlockSurface(surface, *addr));
  455. }
  456.  
  457.  
  458.  
  459. /*
  460.  * Surface fills
  461.  */
  462. HRESULT DDRectFill(LPDIRECTDRAWSURFACE surface, int x, int y, int w, int h, dword colour)
  463. {
  464.     RECT rect;
  465.     DDBLTFX bltfx;
  466.     HRESULT result;
  467.  
  468.     /* Fill the rectangle using a blit */
  469.     SetRect(&rect, x, y, x+w, y+h);
  470.     bltfx.dwSize = sizeof(DDBLTFX);
  471.     bltfx.dwFillColor = (DWORD)colour;
  472.     result = IDirectDrawSurface_Blt(surface, &rect, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &bltfx);
  473.     if (result == DDERR_SURFACELOST) {
  474.         result = IDirectDrawSurface_Restore(surface);
  475.         if (result != DD_OK)
  476.             return result;
  477.         result = IDirectDrawSurface_Blt(surface, &rect, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &bltfx);
  478.     }
  479.     return(result);
  480. }
  481.  
  482. HRESULT DDRectZFill(LPDIRECTDRAWSURFACE surface, int x, int y, int w, int h, dword colour)
  483. {
  484.     RECT rect;
  485.     DDBLTFX bltfx;
  486.     HRESULT result;
  487.  
  488.     SetRect(&rect, x, y, x+w, y+h);
  489.     bltfx.dwSize = sizeof(DDBLTFX);
  490.  
  491. #if 0    // Again, this does not work on NT
  492.     bltfx.dwFillDepth = (DWORD)colour;
  493.     result = IDirectDrawSurface_Blt(surface, &rect, NULL, NULL, DDBLT_DEPTHFILL | DDBLT_WAIT, &bltfx);
  494.     if (result == DDERR_SURFACELOST) {
  495.         result = IDirectDrawSurface_Restore(surface);
  496.         if (result != DD_OK)
  497.             return result;
  498.         result = IDirectDrawSurface_Blt(surface, &rect, NULL, NULL, DDBLT_DEPTHFILL | DDBLT_WAIT, &bltfx);
  499.     }
  500. #else
  501.     bltfx.dwFillColor = (DWORD)colour;
  502.     result = IDirectDrawSurface_Blt(surface, &rect, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &bltfx);
  503.     if (result == DDERR_SURFACELOST) {
  504.         result = IDirectDrawSurface_Restore(surface);
  505.         if (result != DD_OK)
  506.             return result;
  507.         result = IDirectDrawSurface_Blt(surface, &rect, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &bltfx);
  508.     }
  509. #endif
  510.     return(result);
  511. }
  512.  
  513.  
  514.  
  515.  
  516.  
  517.  
  518.  
  519.  
  520.  
  521. /* GL/S3D/DirectDraw low-level functions */
  522.  
  523.  
  524.  
  525.  
  526.  
  527. /*
  528.  * Set render addresses into S3D
  529.  */
  530. void SetRenderAddress(s3MesaContext s3ctx)
  531. {
  532.     void *addr;
  533.     LPDIRECTDRAWSURFACE surface;
  534.     ULONG offset, correction;
  535.     POINT pt;
  536.  
  537.     /* Set Z-buffer up first */
  538.     s3ctx->renderdisabled &= ~2;
  539.     if (s3ctx->z_surface) {
  540.         if (GetSurfaceAddress(s3ctx->z_surface, &addr) != DD_OK) {
  541. #ifdef DEBUG_SURFACES
  542.             fprintf(stderr, "Error locking Z-buffer\n");
  543. #endif
  544.             s3ctx->renderdisabled |= 2;
  545.         } else {
  546.             offset = LinearToPhysical((ULONG) addr) - s3ctx->vram_base;
  547.             s3ctx->s3_z.sfOffset = offset;
  548.             s3f->S3DTK_SetState(s3f, S3DTK_ZBUFFERSURFACE, (ULONG) &s3ctx->s3_z);
  549.  
  550. #ifdef DEBUG_SURFACES
  551.             fprintf(stderr, "Z-buffer set up at offset %x\n", offset);
  552. #endif
  553.  
  554.         }
  555.     }
  556.  
  557.  
  558.     correction = 0;
  559.     if (s3ctx->current_buffer == GL_FRONT) {
  560.         surface = s3ctx->front_surface;
  561.         if (!s3ctx->fullscreen) {
  562.             s3ctx->s3_draw.sfWidth = s3ctx->screen_width;
  563.             s3ctx->s3_draw.sfHeight = s3ctx->screen_height;
  564.             pt.x = pt.y = 0;
  565.             ClientToScreen(s3ctx->hwnd, &pt);
  566.             correction = 2* (pt.x + (pt.y*s3ctx->screen_width));
  567.         }
  568.     } else if (s3ctx->current_buffer == GL_BACK) {
  569.         surface = s3ctx->back_surface;
  570.         if (!s3ctx->fullscreen) {
  571.             s3ctx->s3_draw.sfWidth = s3ctx->window_width;
  572.             s3ctx->s3_draw.sfHeight = s3ctx->window_height;
  573.         }
  574.     } else {
  575. #ifdef DEBUG_SURFACES
  576.         fprintf(stderr, "Buffer other than front/back selected\n");
  577. #endif
  578.         return;
  579.     }
  580.  
  581.     s3ctx->renderdisabled &= ~4;
  582.  
  583.     if (!surface) {
  584.         s3ctx->renderdisabled |= 4;
  585.         return;
  586.     }
  587.  
  588.     if (GetSurfaceAddress(surface, &addr) != DD_OK) {
  589. #ifdef DEBUG_SURFACES
  590.         fprintf(stderr, "Error locking back surface\n");
  591. #endif
  592.         s3ctx->renderdisabled |= 4;
  593.     } else {
  594.         offset = LinearToPhysical((ULONG) addr) - s3ctx->vram_base;
  595.         offset += correction;
  596.         s3ctx->s3_draw.sfOffset = offset;
  597.         s3f->S3DTK_SetState(s3f, S3DTK_DRAWSURFACE, (ULONG) &s3ctx->s3_draw);
  598.  
  599. #ifdef DEBUG_SURFACES
  600.             fprintf(stderr, "Back buffer set up at offset %x\n", offset);
  601. #endif
  602.     }
  603. }
  604.  
  605.  
  606.  
  607.  
  608. /*
  609.  * Double buffer; knows whether to do it by page flip (fullscreen) or blit (windowed)
  610.  */
  611. HRESULT DDDoubleBuffer(HWND hwnd, LPDIRECTDRAWSURFACE front_surface, LPDIRECTDRAWSURFACE back_surface, int width, int height)
  612. {
  613.     HRESULT result;
  614.  
  615. #if USE_FULLSCREEN
  616.  
  617. #ifdef DEBUG_SURFACES
  618.     fprintf(stderr, "Double Buffer by flip\n");
  619. #endif
  620.  
  621.     result = IDirectDrawSurface_Flip(front_surface, NULL, DDFLIP_WAIT);
  622.  
  623.     if (result == DDERR_SURFACELOST) {
  624.         /* One or more surfaces lost, so restore them and try again. This cannot return
  625.          * SURFACELOST again */
  626.         IDirectDrawSurface_Restore(front_surface);
  627.         IDirectDrawSurface_Restore(back_surface);
  628.         result = IDirectDrawSurface_Flip(front_surface, NULL, DDFLIP_WAIT);
  629.     }
  630.  
  631.     return(result);
  632. #else
  633.     POINT pt;
  634.     RECT srect, drect;
  635.  
  636. #ifdef DEBUG_SURFACES
  637.     fprintf(stderr, "Double Buffer by blit\n");
  638. #endif
  639.  
  640.     /* Set the source and destination RECTs */
  641.     SetRect(&srect, 0, 0, width, height);
  642.     SetRect(&drect, 0, 0, width, height);
  643.  
  644.     /* Offset if not fullscreen */
  645.     pt.x = pt.y = 0;
  646.     ClientToScreen(hwnd, &pt);
  647.     OffsetRect(&drect, pt.x, pt.y);
  648.  
  649.     /* Blit the pixels */
  650.     result = IDirectDrawSurface_Blt(front_surface, &drect, back_surface, &srect, DDBLT_WAIT, NULL);
  651.     if (result == DDERR_SURFACELOST) {
  652.         IDirectDrawSurface_Restore(front_surface);
  653.         IDirectDrawSurface_Restore(back_surface);
  654.         result = IDirectDrawSurface_Blt(front_surface, &drect, back_surface, &srect, DDBLT_WAIT, NULL);
  655.     }
  656.     return(result);
  657. #endif
  658. }
  659.  
  660.  
  661.  
  662. /*   Miscellaneous GL functions   */
  663.  
  664.  
  665. /* return buffer size information */
  666. static void buffer_size(GLcontext *ctx, GLuint *width, GLuint *height)
  667. {
  668.     s3MesaContext s3ctx=(s3MesaContext)ctx->DriverCtx;
  669.  
  670. #ifdef DEBUG_GL
  671.     fprintf(stderr, "S3MESA: buffer_size(...)\n");
  672. #endif
  673.  
  674.     *width = s3ctx->width;
  675.     *height = s3ctx->height;
  676. }
  677.  
  678.  
  679. /* Set current drawing color */
  680. static void set_color(GLcontext *ctx, GLubyte red, GLubyte green,
  681.                        GLubyte blue, GLubyte alpha )
  682. {
  683.     s3MesaContext s3ctx=(s3MesaContext)ctx->DriverCtx;
  684.  
  685. #ifdef DEBUG_GL
  686.     fprintf(stderr, "S3MESA: set_color(%d,%d,%d,%d)\n",red,green,blue,alpha);
  687. #endif
  688.  
  689.     s3ctx->color = PACKEDCOLOR(red,green,blue,alpha);
  690. }
  691.  
  692.  
  693. /* implements glClearColor() */
  694. static void clear_color(GLcontext *ctx, GLubyte red, GLubyte green,
  695.                          GLubyte blue, GLubyte alpha )
  696. {
  697.     s3MesaContext s3ctx=(s3MesaContext)ctx->DriverCtx;
  698.  
  699. #ifdef DEBUG_GL
  700.     fprintf(stderr, "S3MESA: clear_color(%d,%d,%d,%d)\n",red,green,blue,alpha);
  701. #endif
  702.  
  703.     s3ctx->clearc = PACKEDCOLOR(red,green,blue,255);
  704.     s3ctx->cleara = alpha;
  705. }
  706.  
  707.  
  708. /*
  709.  * Clear the frame buffer
  710.  *
  711.  * This may need some extra code to allow for clearing the front surface instead
  712.  * of the back surface....
  713.  */
  714. static void clear(GLcontext *ctx, GLboolean all,
  715.                    GLint x, GLint y, GLint width, GLint height )
  716. {
  717.     s3MesaContext s3ctx=(s3MesaContext)ctx->DriverCtx;
  718.     dword col;
  719.  
  720. #if defined(DEBUG_GL) || defined(DEBUG_SURFACES)
  721.     fprintf(stderr, "S3MESA: clear(%d,%d,%d,%d)\n",x,y,width,height);
  722. #endif
  723.  
  724.  
  725.     col =    ((s3ctx->clearc & 0x000000f8) << 7) |
  726.             ((s3ctx->clearc & 0x0000f800) >> 6) |
  727.             ((s3ctx->clearc & 0x00f80000) >> 19);
  728.     DDRectFill(s3ctx->back_surface, 0, 0, s3ctx->width-1, s3ctx->height-1, col);
  729. }
  730.  
  731.  
  732. /*
  733.  * set the buffer used in double buffering
  734.  */
  735. static GLboolean set_buffer(GLcontext *ctx, GLenum mode )
  736. {
  737.     s3MesaContext s3ctx=(s3MesaContext)ctx->DriverCtx;
  738.  
  739. #if defined(DEBUG_GL) || defined(DEBUG_SURFACES)
  740.     fprintf(stderr, "S3MESA: set_buffer(%d)\n",mode);
  741. #endif
  742.  
  743.     if (mode == GL_FRONT)
  744.         s3ctx->current_buffer = mode;
  745.     else if (s3ctx->double_buffer && (mode == GL_BACK))
  746.         s3ctx->current_buffer = mode;
  747.     else
  748.         return(GL_FALSE);
  749.  
  750.     /* Update rendering address */
  751.     SetRenderAddress(s3ctx);
  752.  
  753.     return GL_TRUE;
  754. }
  755.  
  756.  
  757.  
  758.  
  759.  
  760.  
  761.  
  762. /* Bitmap code - this is very slow, and not thoroughly tested */
  763.  
  764. static GLboolean drawbitmap(GLcontext *ctx, GLsizei width, GLsizei height,
  765.                             GLfloat xorig, GLfloat yorig,
  766.                             GLfloat xmove, GLfloat ymove,
  767.                             const struct gl_image *bitmap)
  768. {
  769.     s3MesaContext s3ctx=(s3MesaContext)ctx->DriverCtx;
  770.     word *screen_ptr, *p, color;
  771.     GLubyte *pb;
  772.     int x,y;
  773.     GLint r,g,b,a,px,py,scrwidth,scrheight;
  774.     dword stride;
  775.     LPDIRECTDRAWSURFACE surface;
  776.  
  777. #define ISCLIPPED(rx) ( ((rx)<0) || ((rx)>=scrwidth) )
  778. #define DRAWBIT(i) {                \
  779.         if (!ISCLIPPED(x+px))        \
  780.             if ((*pb) & (1<<(i)))    \
  781.                 (*p) = color;        \
  782.         p++;                        \
  783.         x++;                        \
  784.         if (x >= width) {            \
  785.             pb++;                    \
  786.             break;                    \
  787.         }                            \
  788.     }
  789.  
  790.     scrwidth = s3ctx->width;
  791.     scrheight = s3ctx->height;
  792.  
  793.     px = (GLint)((ctx->Current.RasterPos[0]-xorig)+0.0F);
  794.     py = (GLint)((ctx->Current.RasterPos[1]-yorig)+0.0F);
  795.  
  796.     if ((px>=scrwidth) || (px+width<=0) || (py>=scrheight) || (py+height<=0))
  797.         return GL_TRUE;
  798.  
  799.     pb = (GLubyte *) bitmap->Data;
  800.  
  801.     if(py<0) {
  802.         pb+=(bitmap->Height*(-py)) >> (3+1);
  803.         height+=py;
  804.         py=0;
  805.     }
  806.  
  807.     if (py+height >= scrheight)
  808.         height -= (py+height)-scrheight;
  809.  
  810.     if (s3ctx->current_buffer == GL_FRONT)
  811.         surface = s3ctx->front_surface;
  812.     else
  813.         surface = s3ctx->back_surface;
  814.  
  815.     if (LockSurface(surface, &screen_ptr, &stride) != DD_OK) {
  816.         fprintf(stderr, "Lock failed in drawbitmap\n");
  817.         return GL_TRUE;
  818.     }
  819.     stride >>= 1;    // convert stride to pixels
  820.  
  821.     r = (GLint) (ctx->Current.RasterColor[0]*ctx->Visual->RedScale);
  822.     g = (GLint) (ctx->Current.RasterColor[1]*ctx->Visual->GreenScale);
  823.     b = (GLint) (ctx->Current.RasterColor[2]*ctx->Visual->BlueScale);
  824.     a = (GLint) (ctx->Current.RasterColor[3]*ctx->Visual->AlphaScale);
  825.     color = (word)
  826.             ( ((word)0xf8 & r) << 7) |
  827.             ( ((word)0xf8 & g) << 2) |
  828.             ( ((word)0xf8 & b) >> 3);
  829.  
  830.     /* Very slow */
  831.     for(y=0;y<height;y++) {
  832.         p = screen_ptr + px + ((scrheight-(y+py)) * stride);
  833.  
  834.         for(x=0;;) {
  835.             DRAWBIT(7);    DRAWBIT(6);    DRAWBIT(5);    DRAWBIT(4);
  836.             DRAWBIT(3);    DRAWBIT(2);    DRAWBIT(1);    DRAWBIT(0);
  837.             pb++;
  838.         }
  839.     }
  840.  
  841.     UnlockSurface(surface, screen_ptr);
  842.  
  843. #undef ISCLIPPED
  844. #undef DRAWBIT
  845.  
  846.     return GL_TRUE;
  847. }
  848.  
  849.  
  850. /************************************************************************/
  851.  
  852.  
  853.                             
  854. /*    Setup functions: done with macros for speed and readability */
  855.  
  856. #define NOP(v)
  857.  
  858.  
  859. /* Colour component setup; three modes (plus NOP) */
  860. #define GOURAUD(v) {\
  861.     (v)->R = VB->Color[i][0]; \
  862.     (v)->G = VB->Color[i][1]; \
  863.     (v)->B = VB->Color[i][2]; \
  864.     (v)->A = VB->Color[i][3]; }
  865.  
  866.  
  867.  
  868. #if 0    // Fog does not currently function - although the macros should work, they do not appear to
  869.  
  870. #define FOG(v) {    fv = fog_const*(VB->Clip[i][3] - fog_start);\
  871.                     if (fv > 255.0f) fv = 255.0f; if (fv < 0.0f) fv = 0.0f; \
  872.                     (v)->A = fv; }
  873.  
  874. #define GOURAUDFOG(v) {\
  875.     (v)->R = VB->Color[i][0]; \
  876.     (v)->G = VB->Color[i][1]; \
  877.     (v)->B = VB->Color[i][2]; \
  878.     fv = fog_const*(VB->Clip[i][3] - fog_start); \
  879.     if (fv > 255.0f) fv = 255.0f; if (fv < 0.0f) fv = 0.0f; \
  880.     (v)->A = fv; }
  881.  
  882.  
  883. #else    // Fog disabled
  884.  
  885. #define FOG(v)
  886.  
  887. #define GOURAUDFOG(v) {\
  888.     (v)->R = VB->Color[i][0]; \
  889.     (v)->G = VB->Color[i][1]; \
  890.     (v)->B = VB->Color[i][2]; \
  891.     (v)->A = VB->Color[i][3]; }
  892.  
  893. #endif
  894.  
  895.  
  896. /* Texture component setup */
  897. #define TEXTURE(v)  { \
  898.     (v)->U = uscale*VB->TexCoord[i][0]; \
  899.     (v)->V = vscale*VB->TexCoord[i][1]; \
  900.     (v)->W = wscale*VB->Clip[i][3]; \
  901. }
  902.  
  903.  
  904. /* Z-buffer setup */
  905. #define ZBUFFER(v) { (v)->Z = VB->Win[i][2]; }
  906.  
  907.  
  908.  
  909. /* Macro that builds the appropriate setup function */
  910. #define SETUP( gouraud, texture, depth) {                            \
  911.     register unsigned int i;                                        \
  912.     register struct vertex_buffer *VB = ctx->VB;                    \
  913.     s3MesaContext s3ctx = (s3MesaContext)ctx->DriverCtx;             \
  914.     register S3DTK_VERTEX_TEX *VTB = &s3ctx->vertex_tex[vstart];    \
  915.     register float wscale = s3ctx->wscale;                             \
  916.     register float uscale = (float)s3ctx->ti[s3ctx->currenttex].width;    \
  917.     register float vscale = (float)s3ctx->ti[s3ctx->currenttex].height;    \
  918.     register float yflip = s3ctx->height-1.0f;                        \
  919.     float fog_const = s3ctx->fog_const;                                \
  920.     float fog_start = s3ctx->fog_start;                                \
  921.     float fv;                                                        \
  922.                                                                     \
  923.     for ( i = vstart; i < vend ; i++, VTB++ )                        \
  924.     {                                                                \
  925.         VTB->X = VB->Win[i][0];                                        \
  926.         VTB->Y = yflip - VB->Win[i][1];                                \
  927.         gouraud(VTB);                                                \
  928.         depth(VTB);                                                    \
  929.         texture(VTB);                                                \
  930.     }                                                                \
  931. }
  932.  
  933. static void setup( GLcontext *ctx, GLuint vstart, GLuint vend )
  934. {
  935.     SETUP( NOP, NOP, NOP );
  936. }
  937.     
  938. static void setupG( GLcontext *ctx, GLuint vstart, GLuint vend )
  939. {
  940.     SETUP( GOURAUD, NOP, NOP );
  941. }
  942.  
  943. static void setupT( GLcontext *ctx, GLuint vstart, GLuint vend )
  944. {
  945.     SETUP( NOP, TEXTURE, NOP );
  946. }
  947.     
  948. static void setupGT( GLcontext *ctx, GLuint vstart, GLuint vend )
  949. {
  950.     SETUP( GOURAUD, TEXTURE, NOP );
  951. }
  952.     
  953. static void setupZ( GLcontext *ctx, GLuint vstart, GLuint vend )
  954. {
  955.     SETUP( NOP, NOP, ZBUFFER );
  956. }
  957.     
  958. static void setupGZ( GLcontext *ctx, GLuint vstart, GLuint vend )
  959. {
  960.     SETUP( GOURAUD, NOP, ZBUFFER );
  961. }
  962.  
  963. static void setupTZ( GLcontext *ctx, GLuint vstart, GLuint vend )
  964. {
  965.     SETUP( NOP, TEXTURE, ZBUFFER );
  966. }
  967.     
  968. static void setupGTZ( GLcontext *ctx, GLuint vstart, GLuint vend )
  969. {
  970.     SETUP( GOURAUD, TEXTURE, ZBUFFER );
  971. }
  972.  
  973. static void setupF( GLcontext *ctx, GLuint vstart, GLuint vend )
  974. {
  975.     SETUP( FOG, NOP, NOP );
  976. }
  977.     
  978. static void setupGF( GLcontext *ctx, GLuint vstart, GLuint vend )
  979. {
  980.     SETUP( GOURAUDFOG, NOP, NOP );
  981. }
  982.  
  983. static void setupTF( GLcontext *ctx, GLuint vstart, GLuint vend )
  984. {
  985.     SETUP( FOG, TEXTURE, NOP );
  986. }
  987.     
  988. static void setupGTF( GLcontext *ctx, GLuint vstart, GLuint vend )
  989. {
  990.     SETUP( GOURAUDFOG, TEXTURE, NOP );
  991. }
  992.     
  993. static void setupZF( GLcontext *ctx, GLuint vstart, GLuint vend )
  994. {
  995.     SETUP( FOG, NOP, ZBUFFER );
  996. }
  997.     
  998. static void setupGZF( GLcontext *ctx, GLuint vstart, GLuint vend )
  999. {
  1000.     SETUP( GOURAUDFOG, NOP, ZBUFFER );
  1001. }
  1002.  
  1003. static void setupTZF( GLcontext *ctx, GLuint vstart, GLuint vend )
  1004. {
  1005.     SETUP( FOG, TEXTURE, ZBUFFER );
  1006. }
  1007.     
  1008. static void setupGTZF( GLcontext *ctx, GLuint vstart, GLuint vend )
  1009. {
  1010.     SETUP( GOURAUDFOG, TEXTURE, ZBUFFER );
  1011. }
  1012.     
  1013.  
  1014. /* Gouraud means colour values per-vertex; texture is texture coords (& therefore W)
  1015.  * Z is Z for z-buffering, Fog requires fog setup (in alpha for S3) */
  1016. #define GOURAUD_ENABLED 0x1
  1017. #define TEXTURE_ENABLED 0x2
  1018. #define ZBUFFER_ENABLED 0x4
  1019. #define FOG_ENABLED        0x8
  1020.  
  1021. typedef void (*setup_func)(GLcontext *, GLuint, GLuint);
  1022.  
  1023. setup_func s3SetupFuncs[] = {
  1024.     setup,
  1025.     setupG,
  1026.     setupT,
  1027.     setupGT,
  1028.     setupZ,
  1029.     setupGZ,
  1030.     setupTZ,
  1031.     setupGTZ,
  1032.     setupF,
  1033.     setupGF,
  1034.     setupTF,
  1035.     setupGTF,
  1036.     setupZF,
  1037.     setupGZF,
  1038.     setupTZF,
  1039.     setupGTZF,
  1040. };
  1041.  
  1042. setup_func 
  1043. choose_setup_function( GLcontext *ctx )
  1044. {
  1045.     unsigned int setupIndex = 0;
  1046.  
  1047.     if ( ctx->Light.ShadeModel == GL_SMOOTH && !ctx->Light.Model.TwoSide )
  1048.                                     setupIndex |= GOURAUD_ENABLED;
  1049.     if ( ctx->Texture.Enabled )        setupIndex |= TEXTURE_ENABLED;
  1050.     if ( ctx->Depth.Test )            setupIndex |= ZBUFFER_ENABLED;
  1051.     if ( ctx->Fog.Enabled )            setupIndex |= FOG_ENABLED;
  1052.  
  1053.     return s3SetupFuncs[setupIndex];
  1054. }
  1055.  
  1056.  
  1057.  
  1058.  
  1059.  
  1060.  
  1061. /* ***************************** */
  1062.  
  1063. /* Render functions */
  1064.  
  1065.  
  1066.  
  1067. #undef GOURAUD
  1068.  
  1069. #define GOURAUD(v) { \
  1070.     s3ctx->vertex_tex[(v)].R = VB->Color[(v)][0]; \
  1071.     s3ctx->vertex_tex[(v)].G = VB->Color[(v)][1]; \
  1072.     s3ctx->vertex_tex[(v)].B = VB->Color[(v)][2]; \
  1073.     s3ctx->vertex_tex[(v)].A = VB->Color[(v)][3]; }
  1074.  
  1075. #define FLAT(v) { \
  1076.     s3ctx->vertex_tex[(v)].R = Color[0]; \
  1077.     s3ctx->vertex_tex[(v)].G = Color[1]; \
  1078.     s3ctx->vertex_tex[(v)].B = Color[2]; \
  1079.     s3ctx->vertex_tex[(v)].A = Color[3]; }
  1080.  
  1081.  
  1082.  
  1083.  
  1084. /* Points */
  1085.  
  1086. static void 
  1087. s3Point(GLcontext *ctx, GLuint first, GLuint last)
  1088. {
  1089.     /* Points are not currently supported */
  1090. }
  1091.  
  1092.  
  1093. points_func 
  1094. choose_points_function( GLcontext *ctx )
  1095. {
  1096.    return s3Point;
  1097. }
  1098.  
  1099.  
  1100.  
  1101. /* Lines */
  1102.  
  1103.  
  1104. void RenderLine(S3DTK_VERTEX_TEX *v1, S3DTK_VERTEX_TEX *v2)
  1105. {
  1106.     S3DTK_VERTEX_TEX *v[2];
  1107.  
  1108.     v[0] = v1;
  1109.     v[1] = v2;
  1110.     s3f->S3DTK_TriangleSet(s3f, (ULONG *) &v[0], 2,S3DTK_LINE);
  1111. }
  1112.  
  1113.  
  1114.  
  1115. static void 
  1116. s3LineSmooth(GLcontext *ctx, GLuint v1, GLuint v2, GLuint pv)
  1117. {
  1118.     s3MesaContext s3ctx = (s3MesaContext)ctx->DriverCtx;
  1119.  
  1120.     RenderLine(&s3ctx->vertex_tex[v1], &s3ctx->vertex_tex[v2]);
  1121. }
  1122.  
  1123. static void 
  1124. s3LineSmoothTwoSide(GLcontext *ctx, GLuint v1, GLuint v2, GLuint pv)
  1125. {
  1126.     s3MesaContext s3ctx = (s3MesaContext)ctx->DriverCtx;
  1127.     struct vertex_buffer *VB = ctx->VB;
  1128.  
  1129.     GOURAUD(v1); 
  1130.     GOURAUD(v2); 
  1131.     RenderLine(&s3ctx->vertex_tex[v1], &s3ctx->vertex_tex[v2]);
  1132. }
  1133.  
  1134. static void 
  1135. s3LineFlat(GLcontext *ctx, GLuint v1, GLuint v2, GLuint pv)
  1136. {
  1137.     s3MesaContext s3ctx = (s3MesaContext)ctx->DriverCtx;
  1138.     GLubyte *Color = ctx->VB->Color[pv];
  1139.  
  1140.     FLAT(v1);
  1141.     FLAT(v2);
  1142.     RenderLine(&s3ctx->vertex_tex[v1], &s3ctx->vertex_tex[v2]);
  1143. }
  1144.  
  1145. line_func 
  1146. choose_line_function( GLcontext *ctx )
  1147. {
  1148.    if ( ctx->Light.ShadeModel == GL_SMOOTH )
  1149.       if ( ctx->Light.Model.TwoSide )
  1150.          return s3LineSmoothTwoSide;
  1151.       else
  1152.          return s3LineSmooth;
  1153.    else
  1154.       return s3LineFlat;
  1155. }
  1156.  
  1157.  
  1158.  
  1159. /* Triangles */
  1160.  
  1161. static void 
  1162. s3TriangleSmooth(GLcontext *ctx, GLuint v1, GLuint v2, GLuint v3, GLuint pv)
  1163. {
  1164.     S3DTK_VERTEX_TEX *v[3];
  1165.     s3MesaContext s3ctx = (s3MesaContext)ctx->DriverCtx;
  1166.  
  1167.     v[0] = &s3ctx->vertex_tex[v1];
  1168.     v[1] = &s3ctx->vertex_tex[v2];
  1169.     v[2] = &s3ctx->vertex_tex[v3];
  1170.  
  1171.  
  1172. #ifdef DEBUG_PRIMITIVES
  1173.     fprintf(stderr, "S: %f, %f, %f RGB %d %d %d UVW %f %f %f\n", v[0]->X, v[0]->Y, v[0]->Z, v[0]->R, v[0]->G, v[0]->B, v[0]->U, v[0]->V, v[0]->W);
  1174.     fprintf(stderr, " : %f, %f, %f RGB %d %d %d UVW %f %f %f\n", v[1]->X, v[1]->Y, v[1]->Z, v[1]->R, v[1]->G, v[1]->B, v[1]->U, v[1]->V, v[1]->W);
  1175.     fprintf(stderr, " : %f, %f, %f RGB %d %d %d UVW %f %f %f\n", v[2]->X, v[2]->Y, v[2]->Z, v[2]->R, v[2]->G, v[2]->B, v[2]->U, v[2]->V, v[2]->W);
  1176. #endif
  1177.  
  1178.     s3f->S3DTK_TriangleSet(s3f, (ULONG *) &v[0], 3, S3DTK_TRIFAN);
  1179. }
  1180.  
  1181. static void 
  1182. s3TriangleSmoothTwoSide(GLcontext *ctx, GLuint v1, GLuint v2, GLuint v3, GLuint pv)
  1183. {
  1184.     S3DTK_VERTEX_TEX *v[3];
  1185.     s3MesaContext s3ctx = (s3MesaContext)ctx->DriverCtx;
  1186.     struct vertex_buffer *VB = ctx->VB;
  1187.  
  1188.     GOURAUD(v1); 
  1189.     GOURAUD(v2); 
  1190.     GOURAUD(v3); 
  1191.     v[0] = &s3ctx->vertex_tex[v1];
  1192.     v[1] = &s3ctx->vertex_tex[v2];
  1193.     v[2] = &s3ctx->vertex_tex[v3];
  1194.  
  1195. #ifdef DEBUG_PRIMITIVES
  1196.     fprintf(stderr, "2: %f, %f, %f RGB %d %d %d UVW %f %f %f\n", v[0]->X, v[0]->Y, v[0]->Z, v[0]->R, v[0]->G, v[0]->B, v[0]->U, v[0]->V, v[0]->W);
  1197.     fprintf(stderr, " : %f, %f, %f RGB %d %d %d UVW %f %f %f\n", v[1]->X, v[1]->Y, v[1]->Z, v[1]->R, v[1]->G, v[1]->B, v[1]->U, v[1]->V, v[1]->W);
  1198.     fprintf(stderr, " : %f, %f, %f RGB %d %d %d UVW %f %f %f\n", v[2]->X, v[2]->Y, v[2]->Z, v[2]->R, v[2]->G, v[2]->B, v[2]->U, v[2]->V, v[2]->W);
  1199. #endif
  1200.  
  1201.     s3f->S3DTK_TriangleSet(s3f, (ULONG *) &v[0], 3, S3DTK_TRIFAN);
  1202. }
  1203.  
  1204. static void 
  1205. s3TriangleFlat( GLcontext *ctx, GLuint v1, GLuint v2, GLuint v3, GLuint pv)
  1206. {
  1207.     S3DTK_VERTEX_TEX *v[3];
  1208.     s3MesaContext s3ctx = (s3MesaContext)ctx->DriverCtx;
  1209.     GLubyte *Color = ctx->VB->Color[pv];
  1210.     struct vertex_buffer *VB = ctx->VB;
  1211.  
  1212.     FLAT(v1);
  1213.     FLAT(v2);
  1214.     FLAT(v3);
  1215.     v[0] = &s3ctx->vertex_tex[v1];
  1216.     v[1] = &s3ctx->vertex_tex[v2];
  1217.     v[2] = &s3ctx->vertex_tex[v3];
  1218.  
  1219. #ifdef DEBUG_PRIMITIVES
  1220.     fprintf(stderr, "F: %f, %f, %f RGB %d %d %d UVW %f %f %f\n", v[0]->X, v[0]->Y, v[0]->Z, v[0]->R, v[0]->G, v[0]->B, v[0]->U, v[0]->V, v[0]->W);
  1221.     fprintf(stderr, " : %f, %f, %f RGB %d %d %d UVW %f %f %f\n", v[1]->X, v[1]->Y, v[1]->Z, v[1]->R, v[1]->G, v[1]->B, v[1]->U, v[1]->V, v[1]->W);
  1222.     fprintf(stderr, " : %f, %f, %f RGB %d %d %d UVW %f %f %f\n", v[2]->X, v[2]->Y, v[2]->Z, v[2]->R, v[2]->G, v[2]->B, v[2]->U, v[2]->V, v[2]->W);
  1223. #endif
  1224.  
  1225.     s3f->S3DTK_TriangleSet(s3f, (ULONG *) &v[0], 3, S3DTK_TRIFAN);
  1226. }
  1227.  
  1228. triangle_func 
  1229. choose_triangle_function( GLcontext *ctx )
  1230. {
  1231.    if ( ctx->Light.ShadeModel == GL_SMOOTH )
  1232.       if ( ctx->Light.Model.TwoSide )
  1233.          return s3TriangleSmoothTwoSide;
  1234.       else
  1235.          return s3TriangleSmooth;
  1236.    else
  1237.       return s3TriangleFlat;
  1238. }
  1239.  
  1240.  
  1241.  
  1242. /* Quads */
  1243.  
  1244. static void 
  1245. s3QuadSmooth(GLcontext *ctx, GLuint v1, GLuint v2, GLuint v3, GLuint v4, GLuint pv)
  1246. {
  1247.     s3MesaContext s3ctx = (s3MesaContext)ctx->DriverCtx;
  1248.     S3DTK_VERTEX_TEX *v[4];
  1249.  
  1250.     v[0] = &s3ctx->vertex_tex[v1];
  1251.     v[1] = &s3ctx->vertex_tex[v2];
  1252.     v[2] = &s3ctx->vertex_tex[v3];
  1253.     v[3] = &s3ctx->vertex_tex[v4];
  1254.     s3f->S3DTK_TriangleSet(s3f, (ULONG *) &v[0], 4, S3DTK_TRIFAN);
  1255. }
  1256.  
  1257. static void 
  1258. s3QuadSmoothTwoSide(GLcontext *ctx, GLuint v1, GLuint v2, GLuint v3, GLuint v4, GLuint pv)
  1259. {
  1260.     s3MesaContext s3ctx = (s3MesaContext)ctx->DriverCtx;
  1261.     struct vertex_buffer *VB = ctx->VB;
  1262.     S3DTK_VERTEX_TEX *v[4];
  1263.  
  1264.     GOURAUD(v1); 
  1265.     GOURAUD(v2); 
  1266.     GOURAUD(v3); 
  1267.     GOURAUD(v4); 
  1268.  
  1269.     v[0] = &s3ctx->vertex_tex[v1];
  1270.     v[1] = &s3ctx->vertex_tex[v2];
  1271.     v[2] = &s3ctx->vertex_tex[v3];
  1272.     v[3] = &s3ctx->vertex_tex[v4];
  1273.     s3f->S3DTK_TriangleSet(s3f, (ULONG *) &v[0], 4, S3DTK_TRIFAN);
  1274. }
  1275.  
  1276. static void 
  1277. s3QuadFlat(GLcontext *ctx, GLuint v1, GLuint v2, GLuint v3,GLuint v4, GLuint pv)
  1278. {
  1279.    s3MesaContext s3ctx = (s3MesaContext)ctx->DriverCtx;
  1280.    GLubyte *Color = ctx->VB->Color[pv];
  1281.     S3DTK_VERTEX_TEX *v[4];
  1282.  
  1283.     FLAT(v1);
  1284.     FLAT(v2);
  1285.     FLAT(v3);
  1286.     FLAT(v4);
  1287.  
  1288.     v[0] = &s3ctx->vertex_tex[v1];
  1289.     v[1] = &s3ctx->vertex_tex[v2];
  1290.     v[2] = &s3ctx->vertex_tex[v3];
  1291.     v[3] = &s3ctx->vertex_tex[v4];
  1292.     s3f->S3DTK_TriangleSet(s3f, (ULONG *) &v[0], 4, S3DTK_TRIFAN);
  1293. }
  1294.  
  1295. quad_func 
  1296. choose_quad_function(GLcontext *ctx)
  1297. {
  1298.    if(ctx->Light.ShadeModel == GL_SMOOTH)
  1299.       if(ctx->Light.Model.TwoSide)
  1300.          return s3QuadSmoothTwoSide;
  1301.       else
  1302.          return s3QuadSmooth;
  1303.    else
  1304.       return s3QuadFlat;
  1305. }
  1306.  
  1307.  
  1308.  
  1309. /************************************/
  1310.  
  1311. /* Depth buffer functions */
  1312.  
  1313. static void alloc_depth_buffer(GLcontext *ctx)
  1314. {
  1315.     s3MesaContext s3ctx=(s3MesaContext)ctx->DriverCtx;
  1316.  
  1317. #if defined(DEBUG_GL) || defined(DEBUG_SURFACES)
  1318.     fprintf(stderr, "S3MESA: alloc_depth_buffer()\n");
  1319. #endif
  1320.  
  1321.     if (s3ctx->z_surface) {
  1322.         fprintf(stderr, "Attempt to reallocate Z-buffer; already exists\n");
  1323.         return;
  1324.     }
  1325.  
  1326.     if (DDSetupZSurface(&s3ctx->z_surface, s3ctx->width, s3ctx->height) != DD_OK) {
  1327.         fprintf(stderr, "Failed to set up Z buffer\n");
  1328.         CleanExit(1);
  1329.     }
  1330. }
  1331.  
  1332. static void clear_depth_buffer(GLcontext *ctx)
  1333. {
  1334.     s3MesaContext s3ctx=(s3MesaContext)ctx->DriverCtx;
  1335.  
  1336. #if defined(DEBUG_GL) || defined(DEBUG_SURFACES)
  1337.     fprintf(stderr, "S3MESA: clear_depth_buffer()\n");
  1338. #endif
  1339.  
  1340.     if (ctx->Depth.Test && ctx->Depth.Mask && s3ctx->z_surface)
  1341.         DDRectZFill(s3ctx->z_surface, 0, 0, s3ctx->width-1, s3ctx->height-1, 0xffff);
  1342. }
  1343.  
  1344.  
  1345.  
  1346.  
  1347.  
  1348.  
  1349.  
  1350. /*****************************************/
  1351.  
  1352. static void finish(GLcontext *ctx)
  1353. {
  1354.  
  1355. }
  1356.  
  1357. static void flush(GLcontext *ctx)
  1358. {
  1359.  
  1360. }
  1361.  
  1362.  
  1363.  
  1364.  
  1365. /*****************************************/
  1366.  
  1367.  
  1368. /* Texture support */
  1369.  
  1370.  
  1371. /* S3 utility functions */
  1372.  
  1373.  
  1374. static int UploadTexture(LPDIRECTDRAWSURFACE surface, void *data, int size, void **addr)
  1375. {
  1376.     HRESULT result;
  1377.  
  1378.     if ((result = LockSurface(surface, addr, NULL)) != DD_OK) {
  1379.         fprintf(stderr, "LOCK FAILED, code %x (%d)\n", result, result&0xffff);
  1380.         return(0);
  1381.     } else {
  1382. #ifdef DEBUG_TEXTURES
  1383.         fprintf(stderr, "Lock OK ptr %x\n", addr);
  1384. #endif
  1385.     }
  1386.     memcpy(*addr, data, size);
  1387.     result = UnlockSurface(surface, *addr);
  1388. #ifdef DEBUG_TEXTURES
  1389.     fprintf(stderr, "Unlock returned %x (%d)\n", result, result&0xffff);
  1390. #endif
  1391.  
  1392.     return(1);
  1393. }
  1394.  
  1395.  
  1396. /*
  1397.  * Clear texture caching data out of a texture
  1398.  *
  1399.  * Note that the clearance used has a couple of strange cases, in that
  1400.  * the texture number can be on the cache list twice. In these cases,
  1401.  * the texture may be freed more often than expected. This is not likely to
  1402.  * be a major problem - in cases where it occurs the entire cache will probably
  1403.  * be totally cycled every frame anyway, and the errant case will be cleared
  1404.  * out. This only applies if the texture is deleted.
  1405.  */
  1406. static void UncacheTexture(s3MesaContext s3ctx, int texObject)
  1407. {
  1408.     if (s3ctx->ti[texObject].on_card) {
  1409.         IDirectDrawSurface_Release(s3ctx->ti[texObject].vram_surface);
  1410.         s3ctx->ti[texObject].vram_surface = NULL;
  1411.         s3ctx->ti[texObject].on_card = 0;
  1412.     }
  1413. }
  1414.  
  1415.  
  1416. static void ClearTextureCache(s3MesaContext s3ctx)
  1417. {
  1418.     int i;
  1419.  
  1420.     for(i=0; i<MAXNUM_TEX; i++)
  1421.         UncacheTexture(s3ctx, i);
  1422.  
  1423.     /* Can wipe the head and tail structures as well, since there is
  1424.      * nothing at all left on the card. */
  1425.     s3ctx->texture_cache_head = 0;
  1426.     s3ctx->texture_cache_tail = 0;
  1427. }
  1428.  
  1429.  
  1430.  
  1431.  
  1432. /*
  1433.  * Ensure that a texture is on the card. If couldn't, returns 0, else returns 1
  1434.  */
  1435. static int CacheTexture(s3MesaContext s3ctx, int texObject)
  1436. {
  1437.     texinfo *info = &s3ctx->ti[texObject];
  1438.     void *addr;
  1439.     ULONG offset;
  1440.     HRESULT result;
  1441.     int tail;
  1442.  
  1443.     if (info->on_card) {
  1444.         /* Confirm address and not-lost status */
  1445.         void *addr;
  1446.  
  1447.         if (GetSurfaceAddress(info->vram_surface, &addr) != DD_OK) {
  1448.             fprintf(stderr, "CacheTexture: Address confirmation failed\n");
  1449.             return(0);
  1450.         }
  1451.         offset = LinearToPhysical((ULONG) addr) - s3ctx->vram_base;
  1452.         info->s3_surface.sfOffset = offset;
  1453.  
  1454.         return(1);
  1455.     }
  1456.  
  1457.     /* Try to allocate */
  1458.     do {
  1459.         int width, height;
  1460.  
  1461.         width = info->width;
  1462.         height = info->height;
  1463.  
  1464.         if (info->have_mipmap) {
  1465.             height *= 22;
  1466.             height /= 16;
  1467.         }
  1468.  
  1469.         result = DDSetupTextureSurface(&info->vram_surface, width, height, info->s3_surface.sfFormat);
  1470.         if (result == DD_OK)
  1471.             break;
  1472.  
  1473.         if (s3ctx->texture_cache_head == s3ctx->texture_cache_tail) {
  1474. #ifdef DEBUG_TEXTURES
  1475.             fprintf(stderr, "Texture cache cleared; still cannot allocate\n");
  1476. #endif
  1477.             return(0);
  1478.         }
  1479.  
  1480.         /* Free up one of the existing textures */
  1481.         tail = s3ctx->texture_cache_tail;
  1482.         UncacheTexture(s3ctx, s3ctx->texture_cache[tail]);
  1483.         s3ctx->texture_cache_tail = (tail + 1) % MAXNUM_TEX;
  1484.     } while (1);
  1485.  
  1486.     /* Insert this one onto the cache list */
  1487.     s3ctx->texture_cache[s3ctx->texture_cache_head] = texObject;
  1488.     s3ctx->texture_cache_head = (s3ctx->texture_cache_head + 1) % MAXNUM_TEX;
  1489.     info->on_card = 1;
  1490.  
  1491.     /* Upload it */
  1492.     if (!UploadTexture(info->vram_surface, info->data, info->size, &addr))
  1493.         return(0);
  1494.  
  1495.     /* Set this to the S3 surface data */
  1496.     offset = LinearToPhysical((ULONG) addr) - s3ctx->vram_base;
  1497.     info->s3_surface.sfOffset = offset;
  1498.  
  1499.     return(1);
  1500. }
  1501.  
  1502.  
  1503.  
  1504.  
  1505. /*
  1506.  * Make the chosen texture current for rendering
  1507.  */
  1508. static int SelectTexture(s3MesaContext s3ctx, GLuint texObject)
  1509. {
  1510.     texinfo *info = &s3ctx->ti[texObject];
  1511.  
  1512.     /* Check for a bad texture */
  1513.     if (texObject > MAXNUM_TEX)
  1514.         return(0);
  1515.  
  1516. #ifdef DEBUG_TEXTURES
  1517.     fprintf(stderr, "SelectTexture: (%d), data %x (%d), width %d, height %d\n",
  1518.                 texObject, info->data, info->size, info->width, info->height);
  1519. #endif
  1520.  
  1521.     /* Idiot check */
  1522.     if (!info->data || (info->size > (512*512*2))) {
  1523.         fprintf(stderr, "SelectTexture: idiot check failed in texture %d\n", texObject);
  1524.         return(0);
  1525.     }
  1526.  
  1527.     /* Cache it */
  1528.     if (!CacheTexture(s3ctx, texObject)) {
  1529.         fprintf(stderr, "SelectTexture: Unable to cache texture %d\n", texObject);
  1530.         return(0);
  1531.     }
  1532.  
  1533.     s3f->S3DTK_SetState(s3f, S3DTK_TEXTUREACTIVE, (ULONG) &info->s3_surface);
  1534.  
  1535.     return(1);    // OK
  1536. }
  1537.  
  1538.  
  1539.  
  1540.  
  1541.  
  1542.  
  1543. /*
  1544.  * Based on the minfilter/magfilter values, set up the appropriate filtering mode
  1545.  */
  1546. static void SetFilterMode(texinfo *info)
  1547. {
  1548.     int bilinear;
  1549.     ULONG filtermode;
  1550.  
  1551.     /* Whatever the min filter is, set bilinear according to mag filter */
  1552.     if (info->magfilter == GL_LINEAR)
  1553.         bilinear = 1;
  1554.     else
  1555.         bilinear = 0;
  1556.  
  1557.     if (!info->have_mipmap) {
  1558.         /* No mipmapping */
  1559.         if (bilinear)
  1560.             filtermode = S3DTK_TEX4TPP;
  1561.         else
  1562.             filtermode = S3DTK_TEX1TPP;
  1563.     } else {
  1564.         /* Use minfilter only to select mipmapping */
  1565.         switch(info->minfilter) {
  1566.         case GL_NEAREST:
  1567.         case GL_LINEAR:
  1568.             if (bilinear)
  1569.                 filtermode = S3DTK_TEX4TPP;
  1570.             else
  1571.                 filtermode = S3DTK_TEX1TPP;
  1572.             break;
  1573.         case GL_NEAREST_MIPMAP_NEAREST:
  1574.         case GL_NEAREST_MIPMAP_LINEAR:
  1575.             if (bilinear)
  1576.                 filtermode = S3DTK_TEXM4TPP;
  1577.             else
  1578.                 filtermode = S3DTK_TEXM1TPP;
  1579.             break;
  1580.         case GL_LINEAR_MIPMAP_LINEAR:
  1581.             if (bilinear)
  1582.                 filtermode = S3DTK_TEXM8TPP;
  1583.             else
  1584.                 filtermode = S3DTK_TEXM2TPP;
  1585.             break;
  1586.         }
  1587.     }
  1588.  
  1589.     info->filter = filtermode;
  1590. }
  1591.  
  1592.  
  1593.  
  1594.  
  1595. /*
  1596.  * Set all texture state in S3D
  1597.  */
  1598. static void UpdateTextureState(GLcontext *ctx)
  1599. {
  1600.     s3MesaContext s3ctx=(s3MesaContext)ctx->DriverCtx;
  1601.     ULONG texture_code;
  1602.  
  1603.     /* Set appropriately for lit/unlit textures */
  1604.     texture_code = S3DTK_LITTEXTUREPERSPECT;
  1605.  
  1606.     if (ctx->Texture.Enabled) {
  1607.         /* Nothing much is done in this switch, but retain for later chipsets or if
  1608.          * someone decides that BLEND mode is really required. */
  1609.         switch(ctx->Texture.EnvMode) {
  1610.         case GL_DECAL:
  1611.             /* No changes required */
  1612.             break;
  1613.         case GL_REPLACE:
  1614.             /* This is an unlit texture */
  1615.             texture_code = S3DTK_UNLITTEXTUREPERSPECT;
  1616.             break;
  1617.         case GL_MODULATE:
  1618.             /* This means modulation with the DESTINATION, i.e. a multiplication */
  1619.             /* Not implemented: probably cannot be supported on ViRGE, although if
  1620.              * the texture is a luminance texture, it will probably work out OK anyway
  1621.              * with appropriate alpha format setup. */
  1622.             break;
  1623.         case GL_BLEND:
  1624.             /* This means blend with EnvColor (which is a float[4]) */
  1625.             /* Not implemented: needs a lot of work to support on ViRGE */
  1626.             break;
  1627.         default:
  1628.             fprintf(stderr, "Unknown texture environment mode %x in UpdateTextureStat\n", ctx->Texture.EnvMode);
  1629.             break;
  1630.         }
  1631.  
  1632.         /* Upload the texture, drop to gouraud if it fails, else set texturing on
  1633.          * and set the appropriate filter mode. */
  1634.         if (!SelectTexture(s3ctx, s3ctx->currenttex)) {
  1635. #ifdef DEBUG_TEXTURES
  1636.             fprintf(stderr, "Texture load failed\n");
  1637. #endif
  1638.             s3f->S3DTK_SetState(s3f, S3DTK_RENDERINGTYPE, S3DTK_GOURAUD);
  1639.         } else {
  1640.             s3f->S3DTK_SetState(s3f, S3DTK_RENDERINGTYPE, texture_code);
  1641.             s3f->S3DTK_SetState(s3f, S3DTK_TEXFILTERINGMODE, s3ctx->ti[s3ctx->currenttex].filter);
  1642.  
  1643.             if (s3ctx->ti[s3ctx->currenttex].transparent)
  1644.                 s3f->S3DTK_SetState(s3f, S3DTK_ALPHABLENDING, S3DTK_ALPHATEXTURE);
  1645.         }
  1646.     } else {
  1647.         s3f->S3DTK_SetState(s3f, S3DTK_RENDERINGTYPE, S3DTK_GOURAUD);
  1648.     }
  1649.  
  1650.  
  1651. }
  1652.  
  1653.  
  1654.  
  1655.  
  1656.  
  1657. /*
  1658.  * Texture environment - no action needs to be taken here, as it is put into the
  1659.  * appropriate position by Mesa and will be checked in the next render state update
  1660.  */
  1661. static void texenv(GLcontext *ctx, GLenum pname, const GLfloat *param)
  1662. {
  1663.    GLenum p=(GLenum)(GLint)*param;
  1664.  
  1665. #if defined(DEBUG_GL) || defined(DEBUG_TEXTURES)
  1666.    fprintf(stderr, "S3MESA: texenv pname %x, param %x\n", pname, p);
  1667. #endif
  1668. }
  1669.  
  1670.  
  1671.  
  1672.  
  1673. /*
  1674.  * Texture parameter
  1675.  */
  1676. static void texparam(GLcontext *ctx, GLenum target, GLuint texObject,
  1677.                      GLenum pname, const GLfloat *params)
  1678. {
  1679.     s3MesaContext s3ctx=(s3MesaContext)ctx->DriverCtx;
  1680.     GLenum param=(GLenum)(GLint)params[0];
  1681.  
  1682.     if (texObject >= MAXNUM_TEX)
  1683.         return;
  1684.  
  1685. #if defined(DEBUG_GL) || defined(DEBUG_TEXTURES)
  1686.     fprintf(stderr, "S3MESA: texparam object %d target %x pname %x, param %x\n", texObject, target, pname, param);
  1687. #endif
  1688.  
  1689.     if(target!=GL_TEXTURE_2D) {
  1690. #if !defined(DEBUG_GL) && !defined(DEBUG_TEXTURES)
  1691.         fprintf(stderr,"s3: unsupported texture in texparam()\n");
  1692. #endif
  1693.         return;
  1694.     }
  1695.  
  1696.     switch(pname) {
  1697.     case GL_TEXTURE_MIN_FILTER:
  1698.         switch(param) {
  1699.         case GL_NEAREST:
  1700.         case GL_LINEAR:
  1701.         case GL_NEAREST_MIPMAP_NEAREST:
  1702.         case GL_NEAREST_MIPMAP_LINEAR:
  1703.         case GL_LINEAR_MIPMAP_LINEAR:
  1704.             s3ctx->ti[texObject].minfilter = param;
  1705.             SetFilterMode(&s3ctx->ti[texObject]);
  1706.             break;
  1707.         default:
  1708.             break;
  1709.         }
  1710.         break;
  1711.  
  1712.     case GL_TEXTURE_MAG_FILTER:
  1713.         switch(param) {
  1714.         case GL_NEAREST:
  1715.         case GL_LINEAR:
  1716.             s3ctx->ti[texObject].magfilter = param;
  1717.             SetFilterMode(&s3ctx->ti[texObject]);
  1718.             break;
  1719.         default:
  1720.             break;
  1721.         }
  1722.         break;
  1723.  
  1724.     /* Wrapping/clamp not supported in S3D yet, but will be in future */
  1725.     case GL_TEXTURE_WRAP_S:
  1726.         switch(param) {
  1727.         case GL_CLAMP:
  1728.             break;
  1729.         case GL_REPEAT:
  1730.             break;
  1731.         default:
  1732.             break;
  1733.         }
  1734.         break;
  1735.  
  1736.     case GL_TEXTURE_WRAP_T:
  1737.         switch(param) {
  1738.         case GL_CLAMP:
  1739.             break;
  1740.         case GL_REPEAT:
  1741.             break;
  1742.         default:
  1743.             break;
  1744.         }
  1745.         break;
  1746.  
  1747.     case GL_TEXTURE_BORDER_COLOR:
  1748.         /* TO DO - probably cannot be supported on S3 */
  1749.         break;
  1750.  
  1751.     default:
  1752.         break;
  1753.     }
  1754.  
  1755.     s3ctx->currenttex = texObject;
  1756.     UpdateTextureState(ctx);
  1757. }
  1758.  
  1759.  
  1760.  
  1761. /*
  1762.  * Texture delete
  1763.  */
  1764. static void texdel(GLcontext *ctx, GLuint texObject)
  1765. {
  1766.     s3MesaContext s3ctx=(s3MesaContext)ctx->DriverCtx;
  1767.  
  1768. #if defined(DEBUG_GL) || defined(DEBUG_TEXTURES)
  1769.     fprintf(stderr, "S3MESA: texdel object %d", texObject);
  1770. #endif
  1771.  
  1772.     UncacheTexture(s3ctx, texObject);
  1773.     free(s3ctx->ti[texObject].data);
  1774.     s3ctx->ti[texObject].mipmaplevels = 0;
  1775.     s3ctx->ti[texObject].data = NULL;
  1776. }
  1777.  
  1778.  
  1779.  
  1780.  
  1781.  
  1782.  
  1783. static void texbind(GLcontext *ctx, GLenum target, GLuint texObject)
  1784. {
  1785.     s3MesaContext s3ctx=(s3MesaContext)ctx->DriverCtx;
  1786.  
  1787. #if defined(DEBUG_GL) || defined(DEBUG_TEXTURES)
  1788.     fprintf(stderr, "texbind: object %d\n", texObject);
  1789. #endif
  1790.  
  1791.     if (texObject >= MAXNUM_TEX)
  1792.         return;
  1793.  
  1794.     /* XXX Should probably check for the Dirty flag in the texture image and then
  1795.      * rebuild the image if required */
  1796.  
  1797.     if (texObject == 0)
  1798.         fprintf(stderr, "texbind: NULL OBJECT\n");
  1799.  
  1800.     s3ctx->currenttex = texObject;
  1801.     UpdateTextureState(ctx);
  1802. }
  1803.  
  1804.  
  1805.  
  1806.  
  1807.  
  1808. static int logbase2(int n)
  1809. {
  1810.    GLint i = 1;
  1811.    GLint log2 = 0;
  1812.  
  1813.    if (n<0) {
  1814.       return -1;
  1815.    }
  1816.  
  1817.    while ( n > i ) {
  1818.       i *= 2;
  1819.       log2++;
  1820.    }
  1821.    if (i != n) {
  1822.       return -1;
  1823.    }
  1824.    else {
  1825.       return log2;
  1826.    }
  1827. }
  1828.  
  1829.  
  1830.  
  1831.  
  1832.  
  1833.  
  1834. /*
  1835.  * Copy and convert an OpenGL format texture to S3 texture formats
  1836.  * (RGB8888, RGB4444, RGB1555)
  1837.  *
  1838.  * Returns NULL if it failed to allocate a texture (either a memory failure or
  1839.  * an unsupported format).
  1840.  */
  1841. int TexBuildS3Format(word *dest, const struct gl_texture_image *image, GLint internalFormat, int *transparent, ULONG *s3format)
  1842. {
  1843.     unsigned char r,g,b,a,l,*data;
  1844.     int x,y,w,h,idx;
  1845.  
  1846.     w = image->Width;
  1847.     h = image->Height;
  1848.  
  1849.     *transparent = 0;
  1850.  
  1851.     data = image->Data;
  1852.     switch(internalFormat) {
  1853.     case GL_ALPHA:
  1854.     case GL_ALPHA8:
  1855.     case 1:        // == GL_LUMINANCE
  1856.     case GL_LUMINANCE:
  1857.     case GL_LUMINANCE8:
  1858.         /* This is an alpha map texture */
  1859.         *s3format = S3DTK_TEXARGB4444;
  1860.         for(y=0;y<h;y++)
  1861.             for(x=0;x<w;x++) {
  1862.                 idx = (x + y*w);
  1863.                 l = (gamma_table[data[idx]] & 0xf0) >> 4;
  1864.                 l ^= 15;
  1865.                 dest[x+y*w]= ((word) l << 12);
  1866.             }
  1867.         *transparent = 1;
  1868.         break;
  1869.  
  1870.     case GL_LUMINANCE_ALPHA:
  1871.     case GL_LUMINANCE8_ALPHA8:
  1872.     case 2:
  1873.         return 0;
  1874.         break;
  1875.     case GL_RGB:
  1876.     case GL_RGB8:
  1877.     case 3:
  1878.         /* RGB, no alpha data */
  1879.         *s3format = S3DTK_TEXARGB1555;
  1880.         for(y=0;y<h;y++)
  1881.             for(x=0;x<w;x++) {
  1882.                 idx = (x + y*w) *3;
  1883.                 r = gamma_table[data[idx]];
  1884.                 g = gamma_table[data[idx+1]];
  1885.                 b = gamma_table[data[idx+2]];
  1886.  
  1887.                 dest[x+y*w]= (word)
  1888.                             ( ((word)0xf8 & r) << 7) |
  1889.                             ( ((word)0xf8 & g) << 2) |
  1890.                             ( ((word)0xf8 & b) >> 3); 
  1891.             }
  1892.         break;
  1893.     case GL_RGBA:
  1894.     case GL_RGBA8:
  1895.     case 4:
  1896.         /* RGB with alpha */
  1897.  
  1898.         /* In order to support alpha test completely, this should be a lot more complex
  1899.          * than it is - another copy of the texture is probably needed, and from that
  1900.          * a preprocessed-for-alpha-test image can be generated whenever the alpha test
  1901.          * value changes. This is necessary for Quake. */
  1902.         *s3format = S3DTK_TEXARGB4444;
  1903. //        *transparent = 1;
  1904.         for(y=0;y<h;y++)
  1905.             for(x=0;x<w;x++) {
  1906.                 idx = (x + y*w) *4;
  1907.                 r = gamma_table[data[idx]];
  1908.                 g = gamma_table[data[idx+1]];
  1909.                 b = gamma_table[data[idx+2]];
  1910.                 a = gamma_table[data[idx+3]];
  1911.  
  1912.                 dest[x+y*w]= (word)
  1913.                             ( ((word)0xf0 & a) << 8) |
  1914.                             ( ((word)0xf0 & r) << 4) |
  1915.                               ((word)0xf0 & g)       |
  1916.                             ( ((word)0xf0 & b) >> 4); 
  1917.             }
  1918.         break;
  1919.     default:
  1920.         fprintf(stderr,"S3GL: wrong internalFormat in texbuildimagemap()\n");
  1921.         return 0;
  1922.         break;
  1923.     }
  1924.  
  1925.     return 1;
  1926. }
  1927.  
  1928.  
  1929.  
  1930. /*
  1931.  * Texture image - process and register
  1932.  */
  1933. static void teximg(GLcontext *ctx, GLenum target,
  1934.                    GLuint texObject, GLint level, GLint internalFormat,
  1935.                    const struct gl_texture_image *image)
  1936. {
  1937.     s3MesaContext s3ctx=(s3MesaContext)ctx->DriverCtx;
  1938.     texinfo *ti=s3ctx->ti;
  1939.     word *converted_texture;
  1940.     int transparent;
  1941.     ULONG s3format;
  1942.  
  1943.  
  1944. #ifdef DEBUG_TEXTURES
  1945.     {
  1946.     static int totalsize;
  1947.     int size;
  1948.     char *string;
  1949.  
  1950.     size = image->Width*image->Height;
  1951.  
  1952.     switch(internalFormat) {
  1953.     case GL_ALPHA:
  1954.     case GL_ALPHA8:
  1955.     case GL_LUMINANCE:
  1956.     case GL_LUMINANCE8:
  1957.     case 1:
  1958.         /* byte-per-pixel */
  1959.         string = "1-byte alpha or lum";
  1960.         break;
  1961.  
  1962.     case GL_LUMINANCE_ALPHA:
  1963.     case GL_LUMINANCE8_ALPHA8:
  1964.     case 2:
  1965.         /* 2 bytes-per-pixel */
  1966.         size *= 2;
  1967.         string = "2-byte lum/alpha";
  1968.         break;
  1969.  
  1970.     case GL_RGB:
  1971.     case GL_RGB8:
  1972.     case 3:
  1973.         /* 3 bytes per pixel */
  1974.         size *= 3;
  1975.         string = "3-byte RGB";
  1976.         break;
  1977.  
  1978.     case GL_RGBA:
  1979.     case GL_RGBA8:
  1980.     case 4:
  1981.         /* 4 bytes per pixel */
  1982.         size *= 4;
  1983.         string = "4-byte RGBA";
  1984.         break;
  1985.  
  1986.     default:
  1987.         string = "Strange";
  1988.         size = 0;
  1989.         break;
  1990.     }
  1991.     totalsize += size;
  1992.  
  1993.     fprintf(stderr, "S3MESA: teximg: object %d, target %d, format %d (%s), w/h %d, %d  size %d, totalsize %d\n",
  1994.                             texObject, target, internalFormat, string,
  1995.                             image->Width,
  1996.                             image->Height,
  1997.                             size,
  1998.                             totalsize);
  1999.     }
  2000. #endif
  2001.  
  2002.  
  2003.     /* Limit to maximum number of textures */
  2004.     if (texObject >= MAXNUM_TEX)
  2005.         return;
  2006.  
  2007.     /* Only support 2D target textures : could support 1D with 1-pixel high textures, but
  2008.      * what's the point of a 1D texture anyway? */
  2009.     if (target != GL_TEXTURE_2D)
  2010.         return;
  2011.  
  2012.     /* 512x512 max size */
  2013.     if ((image->Width > 512) || (image->Height > 512))
  2014.         return;
  2015.  
  2016.     /* Power of 2 on both axes only */
  2017.     if ( (logbase2(image->Width) < 0) || (logbase2(image->Height) < 0) )
  2018.         return;
  2019.  
  2020.     /* Free texture if there's one already in this slot */
  2021. //    if (ti[texObject].mipmaplevels)
  2022. //        texdel(ctx, texObject);
  2023.  
  2024.     /* For first level only, allocate space for all levels and clear the base data */
  2025.     if (level == 0) {
  2026.         /* At the moment, all formats go to 16-bit destination textures: also allocate enough
  2027.          * space for any mipmaps */
  2028.         if (!(converted_texture = (word *) malloc(sizeof(word) * image->Width*image->Height * 22/16))) {
  2029.             fprintf(stderr,"S3GL: out of memory !\n");
  2030.             return;
  2031.         }
  2032.         ti[texObject].data = converted_texture;
  2033.         ti[texObject].size = 0;
  2034.         ti[texObject].have_mipmap = 0;
  2035.         ti[texObject].width = image->Width;
  2036.         ti[texObject].height = image->Height;
  2037.         ti[texObject].s3_surface.sfWidth = image->Width;
  2038.         ti[texObject].s3_surface.sfHeight = image->Height;
  2039.  
  2040.         /* Don't set filtering mode as it can be set before upload */
  2041.     } else {
  2042.         converted_texture = (word *) ((char *) ti[texObject].data + ti[texObject].size);
  2043.         ti[texObject].have_mipmap = 1;        // Should probably only set this when I have _all_ the mipmaps
  2044.     }
  2045.  
  2046.     /* Convert the texture from GL to a supported S3 format */
  2047.     if (!TexBuildS3Format(converted_texture, image, internalFormat, &transparent, &s3format)) {
  2048. #ifndef DEBUG_TEXTURES
  2049.         fprintf(stderr,"S3GL: unsupported texture in teximg()\n");
  2050. #endif
  2051.         free(converted_texture);
  2052.         return;
  2053.     }
  2054.  
  2055.     /* Update for this level */
  2056.     ti[texObject].size += image->Width*image->Height*2;
  2057.     ti[texObject].transparent |= transparent;
  2058.     ti[texObject].s3_surface.sfFormat = s3format | S3DTK_VIDEO;
  2059.     ti[texObject].mipmaplevels++;
  2060.  
  2061.     SetFilterMode(&ti[texObject]);
  2062.  
  2063.     /* This becomes the current texture */
  2064.     s3ctx->currenttex = texObject;
  2065.     UpdateTextureState(ctx);
  2066. }
  2067.  
  2068.  
  2069.  
  2070.  
  2071.  
  2072.  
  2073. /*
  2074.  * Set the near and far clipping planes into the driver
  2075.  *
  2076.  * Necessary because fog depends on the w values passed down (which go from n to f)
  2077.  */
  2078. static void SetNearFar( GLcontext *ctx, GLfloat n, GLfloat f)
  2079. {
  2080.     s3MesaContext s3ctx = (s3MesaContext)ctx->DriverCtx;
  2081.  
  2082.     if(s3ctx) {
  2083.         s3ctx->hither    = fabs(n);
  2084.         s3ctx->yon        = fabs(f);
  2085.         s3ctx->wscale    = 65535.0f / s3ctx->yon;
  2086.  
  2087.         /*
  2088.          * Recompute fog coefficients
  2089.          */
  2090.         if(ctx->Fog.Enabled) {
  2091.             switch(ctx->Fog.Mode)    {
  2092.             case GL_LINEAR:
  2093.                 break;
  2094.             case GL_EXP:
  2095.                 break;
  2096.             case GL_EXP2:
  2097.                 break;
  2098.             default: /* That should never happen */
  2099.                 break; 
  2100.             }
  2101.         }
  2102.     }
  2103. }
  2104.  
  2105. void s3MesaSetNearFar(GLfloat n, GLfloat f)
  2106. {
  2107.     SetNearFar(Currents3MesaCtx->gl_ctx, n, f);
  2108. }
  2109.  
  2110.  
  2111.  
  2112.  
  2113.  
  2114.  
  2115.  
  2116.  
  2117. /*
  2118.  * Configure hardware state
  2119.  */
  2120. static void SetS3RenderState(GLcontext *ctx)
  2121. {
  2122.     s3MesaContext s3ctx=(s3MesaContext)ctx->DriverCtx;
  2123.  
  2124.     if(ctx->Color.BlendEnabled) {
  2125.         switch(ctx->Color.BlendSrc) {
  2126.         case GL_ZERO:
  2127.         case GL_ONE:
  2128.         case GL_DST_COLOR:
  2129.         case GL_ONE_MINUS_DST_COLOR:
  2130.         case GL_SRC_ALPHA:
  2131.         case GL_ONE_MINUS_SRC_ALPHA:
  2132.         case GL_SRC_ALPHA_SATURATE:
  2133.         case GL_SRC_COLOR:
  2134.         case GL_ONE_MINUS_SRC_COLOR:
  2135.         case GL_DST_ALPHA:
  2136.         case GL_ONE_MINUS_DST_ALPHA:
  2137.         default:
  2138.             /* No src/dest factors for S3 yet - leave for later chipsets */
  2139.             break;
  2140.         }
  2141.  
  2142.         switch(ctx->Color.BlendDst) {
  2143.         case GL_ZERO:
  2144.         case GL_ONE:
  2145.         case GL_SRC_COLOR:
  2146.         case GL_ONE_MINUS_SRC_COLOR:
  2147.         case GL_SRC_ALPHA:
  2148.         case GL_ONE_MINUS_SRC_ALPHA:
  2149.         case GL_SRC_ALPHA_SATURATE:
  2150.         case GL_DST_COLOR:
  2151.         case GL_ONE_MINUS_DST_COLOR:
  2152.         case GL_DST_ALPHA:
  2153.         case GL_ONE_MINUS_DST_ALPHA:
  2154.         default:
  2155.             /* No src/dest factors for S3 yet - leave for later chipsets */
  2156.             break;
  2157.         }
  2158.  
  2159.         s3f->S3DTK_SetState(s3f, S3DTK_ALPHABLENDING, S3DTK_ALPHASOURCE);
  2160.  
  2161.         /* The S3 only supports one of alpha texture and alpha source... so
  2162.          * which do I select? */
  2163.         if (ctx->Texture.Enabled && s3ctx->ti[s3ctx->currenttex].transparent) {
  2164.  
  2165. #ifdef DEBUG_STATE
  2166.             fprintf(stderr, "Alpha source/texture conflict!\n");
  2167. #endif
  2168.  
  2169.             s3f->S3DTK_SetState(s3f, S3DTK_ALPHABLENDING, S3DTK_ALPHATEXTURE);
  2170.         } else if (ctx->Fog.Enabled) {
  2171.             /* Can't do source alpha blend and fog at the same time either! */
  2172. #ifdef DEBUG_STATE
  2173.             fprintf(stderr, "Alpha source/fog conflict!\n");
  2174. #endif
  2175.             s3f->S3DTK_SetState(s3f, S3DTK_ALPHABLENDING, S3DTK_ALPHAOFF);
  2176.         }
  2177.     } else {
  2178.         if (s3ctx->ti[s3ctx->currenttex].transparent)
  2179.             s3f->S3DTK_SetState(s3f, S3DTK_ALPHABLENDING, S3DTK_ALPHATEXTURE);
  2180.         else
  2181.             s3f->S3DTK_SetState(s3f, S3DTK_ALPHABLENDING, S3DTK_ALPHAOFF);
  2182.     }
  2183.  
  2184.     UpdateTextureState(ctx);
  2185.  
  2186.  
  2187.     /* Depth buffer config */
  2188.     if (!ctx->Depth.Test) {
  2189.         /* Disable Z-buffer */
  2190. #ifdef DEBUG_STATE
  2191.         fprintf(stderr,"Z-buffering not enabled\n");
  2192. #endif
  2193.         s3f->S3DTK_SetState(s3f, S3DTK_ZBUFFERENABLE, S3DTK_OFF);
  2194.     } else {
  2195.         /* Enable Z-buffer */
  2196.         s3f->S3DTK_SetState(s3f, S3DTK_ZBUFFERENABLE, S3DTK_ON);
  2197.  
  2198.         /* Set compare function */
  2199.         switch(ctx->Depth.Func) {
  2200.         case GL_NEVER:
  2201.             s3f->S3DTK_SetState(s3f, S3DTK_ZBUFFERCOMPAREMODE, S3DTK_ZNEVERPASS);
  2202.             break;
  2203.         case GL_LESS:
  2204.             s3f->S3DTK_SetState(s3f, S3DTK_ZBUFFERCOMPAREMODE, S3DTK_ZSRCLSZFB);
  2205.             break;
  2206.         case GL_GEQUAL:
  2207.             s3f->S3DTK_SetState(s3f, S3DTK_ZBUFFERCOMPAREMODE, S3DTK_ZSRCGEZFB);
  2208.             break;
  2209.         case GL_LEQUAL:
  2210.             s3f->S3DTK_SetState(s3f, S3DTK_ZBUFFERCOMPAREMODE, S3DTK_ZSRCLEZFB);
  2211.             break;
  2212.         case GL_GREATER:
  2213.             s3f->S3DTK_SetState(s3f, S3DTK_ZBUFFERCOMPAREMODE, S3DTK_ZSRCGTZFB);
  2214.             break;
  2215.         case GL_NOTEQUAL:
  2216.             s3f->S3DTK_SetState(s3f, S3DTK_ZBUFFERCOMPAREMODE, S3DTK_ZSRCNEZFB);
  2217.             break;
  2218.         case GL_EQUAL:
  2219.             s3f->S3DTK_SetState(s3f, S3DTK_ZBUFFERCOMPAREMODE, S3DTK_ZSRCEQZFB);
  2220.             break;
  2221.         case GL_ALWAYS:
  2222.             s3f->S3DTK_SetState(s3f, S3DTK_ZBUFFERCOMPAREMODE, S3DTK_ZALWAYSPASS);
  2223.             break;
  2224.         default:
  2225.             break;
  2226.         }
  2227.         /* Set write on or off */
  2228.         if (ctx->Depth.Mask)
  2229.             s3f->S3DTK_SetState(s3f, S3DTK_ZBUFFERUPDATEENABLE, S3DTK_ON);
  2230.         else
  2231.             s3f->S3DTK_SetState(s3f, S3DTK_ZBUFFERUPDATEENABLE, S3DTK_OFF);
  2232.     }
  2233.  
  2234.  
  2235. #ifdef DEBUG_STATE
  2236.    if(ctx->Color.AlphaEnabled)
  2237.        fprintf(stderr, "Alpha test enabled, func %d, ref %d\n", ctx->Color.AlphaFunc, ctx->Color.AlphaRefUbyte);
  2238. #endif
  2239.  
  2240. #if 0
  2241.    if(ctx->Color.AlphaEnabled) {
  2242.       switch(ctx->Color.AlphaFunc) {
  2243.          case GL_NEVER:
  2244.             grAlphaTestFunction(GR_CMP_NEVER);
  2245.             break;
  2246.          case GL_LESS:
  2247.             grAlphaTestFunction(GR_CMP_LESS);
  2248.             break;
  2249.          case GL_EQUAL:
  2250.             grAlphaTestFunction(GR_CMP_EQUAL);
  2251.             break;
  2252.          case GL_LEQUAL:
  2253.             grAlphaTestFunction(GR_CMP_LEQUAL);
  2254.             break;
  2255.          case GL_GREATER:
  2256.             grAlphaTestFunction(GR_CMP_GREATER);
  2257.             break;
  2258.          case GL_NOTEQUAL:
  2259.             grAlphaTestFunction(GR_CMP_NOTEQUAL);
  2260.             break;
  2261.          case GL_GEQUAL:
  2262.             grAlphaTestFunction(GR_CMP_GEQUAL);
  2263.             break;
  2264.          case GL_ALWAYS:
  2265.             grAlphaTestFunction(GR_CMP_ALWAYS);
  2266.             break;
  2267.          default:
  2268.             break;
  2269.       }
  2270.       grAlphaTestReferenceValue(ctx->Color.AlphaRefUbyte);
  2271.    }
  2272.    else
  2273.       grAlphaTestFunction(GR_CMP_ALWAYS);
  2274. #endif
  2275.  
  2276.  
  2277.  
  2278.  
  2279. #if 0        // Disabled, as fog is playing up at the moment
  2280.     /* Fogging */
  2281.     if (ctx->Fog.Enabled) {
  2282.         word fog_colour;
  2283.  
  2284.         fog_colour =     ((word) (0x1f * ctx->Fog.Color[0]) << 10) |
  2285.                         ((word) (0x1f * ctx->Fog.Color[1]) << 5) |
  2286.                         (word) (0x1f * ctx->Fog.Color[2]);
  2287.         /* In-case check */
  2288.         if (fog_colour = S3DTK_FOGOFF)
  2289.             fog_colour ++;
  2290.         s3f->S3DTK_SetState(s3f, S3DTK_FOGCOLOR, fog_colour);
  2291.  
  2292.         switch(ctx->Fog.Mode)    {
  2293.         case GL_LINEAR:
  2294.             /* These need to be set up then on a per-vertex basis into the alpha component */
  2295.             s3ctx->fog_start = ctx->Fog.Start;
  2296.             s3ctx->fog_end = ctx->Fog.End;
  2297.             s3ctx->fog_const = 255.0f / (s3ctx->fog_end - s3ctx->fog_start);
  2298.             break;
  2299.         case GL_EXP:
  2300.         case GL_EXP2:
  2301.             /* Use fog.Density... not supported atm */
  2302.             s3f->S3DTK_SetState(s3f, S3DTK_FOGCOLOR, S3DTK_FOGOFF);
  2303.             break;
  2304.         default:
  2305.             s3f->S3DTK_SetState(s3f, S3DTK_FOGCOLOR, S3DTK_FOGOFF);
  2306.             break;
  2307.         }
  2308.  
  2309.     } else
  2310.         s3f->S3DTK_SetState(s3f, S3DTK_FOGCOLOR, S3DTK_FOGOFF);
  2311. #endif
  2312. }
  2313.  
  2314.  
  2315. static const char *renderer_string(void)
  2316. {
  2317.    return "S3GL V0.1";
  2318. }
  2319.  
  2320.  
  2321.  
  2322.  
  2323. /*
  2324.  * Stub functions; prevents things that use accumulation buffers crashing
  2325.  */
  2326. void ReadColorSpan(    GLcontext *ctx,
  2327.                     GLuint n, GLint x, GLint y,
  2328.                     GLubyte red[], GLubyte green[],
  2329.                     GLubyte blue[], GLubyte alpha[] )
  2330. {
  2331. }
  2332.  
  2333.  
  2334.  
  2335.  
  2336. /*
  2337.  * Writing of colour spans
  2338.  *
  2339.  * This is not very fast
  2340.  */
  2341. void WriteColorSpan(GLcontext *ctx,
  2342.                     GLuint n, GLint x, GLint y,
  2343.                     const GLubyte red[], const GLubyte green[],
  2344.                     const GLubyte blue[], const GLubyte alpha[],
  2345.                     const GLubyte mask[] )
  2346. {
  2347.     int i, offset;
  2348.     dword stride;
  2349.     word colour, *screen_ptr;
  2350.     LPDIRECTDRAWSURFACE *surface;
  2351.     s3MesaContext s3ctx=(s3MesaContext)ctx->DriverCtx;
  2352.  
  2353.     if (s3ctx->current_buffer == GL_FRONT)
  2354.         surface = s3ctx->front_surface;
  2355.     else
  2356.         surface = s3ctx->back_surface;
  2357.  
  2358.     if (LockSurface(surface, &screen_ptr, &stride) != DD_OK) {
  2359.         fprintf(stderr, "Lock failed in drawbitmap\n");
  2360.         return GL_TRUE;
  2361.     }
  2362.     stride >>= 1;    // convert stride to pixels
  2363.  
  2364.     offset = y*stride + x;
  2365.  
  2366.     if (mask) {
  2367.         /* draw some pixels */
  2368.         for (i=0; i<n; i++, x++) {
  2369.             if (mask[i]) {
  2370.                 colour = (word)
  2371.                     ( ((word)0xf8 &      red[i]) << 7) |
  2372.                     ( ((word)0xf8 & green[i]) << 2) |
  2373.                     ( ((word)0xf8 &  blue[i]) >> 3);
  2374.                 screen_ptr[i+offset] = colour;
  2375.             }
  2376.         }
  2377.     } else {
  2378.         /* draw all pixels */
  2379.         for (i=0; i<n; i++, x++) {
  2380.             colour = (word)
  2381.                 ( ((word)0xf8 &      red[i]) << 7) |
  2382.                 ( ((word)0xf8 & green[i]) << 2) |
  2383.                 ( ((word)0xf8 &  blue[i]) >> 3);
  2384.             screen_ptr[i+offset] = colour;
  2385.         }
  2386.     }
  2387.  
  2388.     UnlockSurface(surface, screen_ptr);
  2389. }
  2390.  
  2391.  
  2392.  
  2393. /*
  2394.  * GL render state has changed, so update
  2395.  */
  2396. static void SetRenderState(GLcontext *ctx)
  2397. {
  2398. #if defined(DEBUG_GL) || defined(DEBUG_STATE)
  2399.     fprintf(stderr, "S3MESA: SetRenderState()\n");
  2400. #endif
  2401.  
  2402.     SetS3RenderState(ctx);
  2403.  
  2404.     ctx->Driver.PointsFunc        = choose_points_function(ctx);
  2405.     ctx->Driver.LineFunc        = choose_line_function(ctx);
  2406.     ctx->Driver.TriangleFunc    = choose_triangle_function(ctx);
  2407.     ctx->Driver.QuadFunc        = choose_quad_function(ctx);
  2408.     ctx->Driver.RectFunc        = NULL;
  2409.  
  2410.     ctx->Driver.RasterSetup        = choose_setup_function(ctx);
  2411.     ctx->Driver.RenderVB        = NULL;
  2412. }
  2413.  
  2414.  
  2415. /*
  2416.  * Dummy renderer if rendering blocker
  2417.  */
  2418. void dummy(void)
  2419. {
  2420. }
  2421.  
  2422.  
  2423. /*
  2424.  * Build the device driver entries in the dispatch tables
  2425.  */
  2426. static void BuildDispatchTable(GLcontext *ctx)
  2427. {
  2428.     s3MesaContext s3ctx=(s3MesaContext)ctx->DriverCtx;
  2429.  
  2430. #if defined(DEBUG_GL) || defined (DEBUG_STATE)
  2431.     fprintf(stderr, "S3MESA: s3_mesa_setup_dd_pointers()\n");
  2432. #endif
  2433.  
  2434.     /* It would be preferable just to call SetRenderState here, but since
  2435.      * the pointers can be changed at the higher level, this is not a good idea.
  2436.      * This is a very strange bug in Mesa. */
  2437.  
  2438.     ctx->Driver.UpdateState        = BuildDispatchTable;
  2439.      
  2440.     ctx->Driver.RendererString    = renderer_string;
  2441.  
  2442.     ctx->Driver.NearFar            = SetNearFar;
  2443.  
  2444.     ctx->Driver.Index            = NULL;
  2445.     ctx->Driver.Color            = set_color;
  2446.     ctx->Driver.ClearColor        = clear_color;
  2447.  
  2448.     ctx->Driver.AllocDepthBuffer = alloc_depth_buffer;
  2449.  
  2450.     ctx->Driver.SetBuffer        = set_buffer;
  2451.     ctx->Driver.GetBufferSize    = buffer_size;
  2452.  
  2453.     /* Texture stuff will still function even if rendering is knocked out */
  2454.     ctx->Driver.TexEnv            = texenv;
  2455.     ctx->Driver.TexImage        = teximg;
  2456.     ctx->Driver.TexParameter    = texparam;
  2457.     ctx->Driver.BindTexture        = texbind;
  2458.     ctx->Driver.DeleteTexture    = texdel;
  2459.  
  2460.     if (s3ctx->renderdisabled) {
  2461.         /* Blocking rendering */
  2462.  
  2463.         /* This currently gives a very large number of warnings */
  2464.         ctx->Driver.ClearIndex        = NULL;
  2465.         ctx->Driver.Clear            = dummy;
  2466.  
  2467.         ctx->Driver.ClearDepthBuffer = dummy;
  2468.  
  2469.         ctx->Driver.Bitmap            = dummy;
  2470.         ctx->Driver.DrawPixels        = NULL;
  2471.  
  2472.         ctx->Driver.Finish            = dummy;
  2473.         ctx->Driver.Flush            = dummy;
  2474.  
  2475.         ctx->Driver.WriteColorSpan       = dummy;
  2476.         ctx->Driver.WriteMonocolorSpan   = NULL;
  2477.         ctx->Driver.WriteColorPixels     = NULL;
  2478.         ctx->Driver.WriteMonocolorPixels = NULL;
  2479.         ctx->Driver.WriteIndexSpan       = NULL;
  2480.         ctx->Driver.WriteMonoindexSpan   = NULL;
  2481.         ctx->Driver.WriteIndexPixels     = NULL;
  2482.         ctx->Driver.WriteMonoindexPixels = NULL;
  2483.  
  2484.         ctx->Driver.ReadIndexSpan    = NULL;
  2485.         ctx->Driver.ReadColorSpan    = dummy;
  2486.         ctx->Driver.ReadIndexPixels = NULL;
  2487.         ctx->Driver.ReadColorPixels = NULL;
  2488.  
  2489.  
  2490.         ctx->Driver.PointsFunc        = dummy;
  2491.         ctx->Driver.LineFunc        = dummy;
  2492.         ctx->Driver.TriangleFunc    = dummy;
  2493.         ctx->Driver.QuadFunc        = dummy;
  2494.         ctx->Driver.RectFunc        = NULL;
  2495.  
  2496.         ctx->Driver.RasterSetup        = dummy;
  2497.         ctx->Driver.RenderVB        = NULL;
  2498.  
  2499.  
  2500.     } else {
  2501.         /* Normal, working stuff */
  2502.         ctx->Driver.ClearIndex        = NULL;
  2503.         ctx->Driver.Clear            = clear;
  2504.  
  2505.         ctx->Driver.ClearDepthBuffer = clear_depth_buffer;
  2506.  
  2507.         ctx->Driver.Bitmap            = drawbitmap;
  2508.         ctx->Driver.DrawPixels        = NULL;
  2509.  
  2510.         ctx->Driver.Finish            = flush;
  2511.         ctx->Driver.Flush            = finish;
  2512.  
  2513.         ctx->Driver.WriteColorSpan       = WriteColorSpan;
  2514.         ctx->Driver.WriteMonocolorSpan   = NULL;
  2515.         ctx->Driver.WriteColorPixels     = NULL;
  2516.         ctx->Driver.WriteMonocolorPixels = NULL;
  2517.         ctx->Driver.WriteIndexSpan       = NULL;
  2518.         ctx->Driver.WriteMonoindexSpan   = NULL;
  2519.         ctx->Driver.WriteIndexPixels     = NULL;
  2520.         ctx->Driver.WriteMonoindexPixels = NULL;
  2521.  
  2522.         ctx->Driver.ReadIndexSpan    = NULL;
  2523.         ctx->Driver.ReadColorSpan    = ReadColorSpan;
  2524.         ctx->Driver.ReadIndexPixels = NULL;
  2525.         ctx->Driver.ReadColorPixels = NULL;
  2526.  
  2527.         SetRenderState(ctx);
  2528.     }
  2529. }
  2530.  
  2531.  
  2532.  
  2533. s3MesaContext s3MesaCreateBestContext(GLuint win,GLint width, GLint height,
  2534.                                       const GLint attribList[])
  2535. {
  2536.  
  2537.     /* Need to set up the best resolution choice here in case width, height are not
  2538.      * exactly supported */
  2539.  
  2540. #if USE_FULLSCREEN
  2541.     if (
  2542.         ((width == 320) && (height == 200)) ||
  2543.         ((width == 512) && (height == 384)) ||
  2544.         ((width == 640) && (height == 480)) ||
  2545.         ((width == 800) && (height == 600)) ) {
  2546.         /* Everything's OK. Nothing done here, it's just that reversing
  2547.          * THAT if would be a bloody nightmare */
  2548.     } else {
  2549.         /* Pretty simple this */
  2550.         if (width <= 400) {
  2551.             width = 320;
  2552.             height = 200;
  2553.         } else {
  2554.             width = 640;
  2555.             height = 480;
  2556.         }
  2557.     }
  2558. #endif
  2559.  
  2560.     return s3MesaCreateContext(win, width, height, attribList);
  2561. }
  2562.  
  2563.  
  2564.  
  2565. #ifdef __WIN32__
  2566. static int cleangraphics(void)
  2567. {
  2568.    s3MesaDestroyContext(Currents3MesaCtx);
  2569.  
  2570.    return 0;
  2571. }
  2572. #endif
  2573.  
  2574.  
  2575.  
  2576.  
  2577.  
  2578. int s3mesa_context_count;        // How many device contexts are currently running
  2579.  
  2580. /*
  2581.  * Fundamental initialisation and device startup; this is only done if no
  2582.  * contexts are currently running.
  2583.  *
  2584.  * Initialise DirectDraw and S3 libraries; pick up the front buffer
  2585.  */
  2586. void s3MesaFundamentalInit(HWND hwnd)
  2587. {
  2588.     S3DTK_LIB_INIT lib_init;
  2589.     S3DTK_RENDERER_INITSTRUCT renderer_init;
  2590.     HRESULT result;
  2591.     ULONG rv;
  2592.  
  2593.  
  2594. #ifndef S3_SILENT
  2595.     fprintf(stderr,"Mesa S3 Device Driver\n");
  2596. #endif
  2597.  
  2598.     /* Initialise S3 and DirectDraw */
  2599.     if ((result = DirectDrawCreate(NULL, &gpDD, NULL)) != DD_OK) {
  2600.         fprintf(stderr, "Error starting DirectDraw\n");
  2601.         CleanExit(1);
  2602.     }
  2603.  
  2604.     /* Start S3 libraries */
  2605.     lib_init.libFlags = S3DTK_INITPIO | S3DTK_INIT2D_SERIALIZATION_ON;
  2606.     rv = S3DTK_InitLib((ULONG) &lib_init);
  2607.     if (rv != S3DTK_OK) {
  2608.         fprintf(stderr, "Error starting S3DTK\n");
  2609.         CleanExit(1);
  2610.     }
  2611.  
  2612.     /* Get the renderer object */
  2613.     renderer_init.initFlags = S3DTK_FORMAT_FLOAT | S3DTK_VERIFY_UVRANGE | S3DTK_VERIFY_XYRANGE;
  2614.     rv = S3DTK_CreateRenderer((ULONG) &renderer_init, &s3f);
  2615.     if (rv != S3DTK_OK) {
  2616.         fprintf(stderr, "Error starting S3DTK\n");
  2617.         CleanExit(1);
  2618.     }
  2619.  
  2620. #if !USE_FULLSCREEN
  2621.     if(IDirectDraw_SetCooperativeLevel(gpDD, hwnd, DDSCL_NORMAL) != DD_OK) {
  2622. #ifndef S3_SILENT
  2623.         fprintf(stderr, "Failed to set cooperative level %x (%d), hwnd %x\n", result, result&0xffff, hwnd);
  2624. #endif
  2625.         CleanExit(1);
  2626.     }
  2627.  
  2628.     /* Get the front surface used for everything */
  2629.     DDSetupPrimarySurface(&front_surface);
  2630. #endif
  2631.  
  2632. #ifdef DEBUG_INIT
  2633.     fprintf(stderr, "DirectDraw and S3 libraries running OK\n");
  2634. #endif
  2635. }
  2636.  
  2637.  
  2638. /*
  2639.  * Fundamental device shutdown; done when the last context is closed
  2640.  *
  2641.  * Clear out the S3 libraries and DirectDraw
  2642.  */
  2643. void s3MesaFundamentalShutdown(void)
  2644. {
  2645.     S3DTK_DestroyRenderer(&s3f);
  2646.     S3DTK_ExitLib();
  2647.     IDirectDraw_Release(gpDD);
  2648. }
  2649.  
  2650.  
  2651.  
  2652.  
  2653.  
  2654. /*
  2655.  * Create a new S3/Mesa context and return a handle to it.
  2656.  */
  2657. s3MesaContext s3MesaCreateContext(GLuint win, int width, int height, const GLint attribList[])
  2658. {
  2659.     s3MesaContext s3ctx;
  2660.     int i;
  2661.     GLboolean doubleBuffer = GL_FALSE;
  2662.     GLboolean alphaBuffer = GL_FALSE;
  2663.     GLint depthSize = 0;
  2664.     GLint stencilSize = 0;
  2665.     GLint accumSize = 0;
  2666.     HRESULT result;
  2667.     RECT rect;
  2668.     HWND hwnd = (HWND) win;
  2669.     S3DTK_RECTAREA s3rect;
  2670.     DDSURFACEDESC ddsd;//Raja
  2671.  
  2672.     BuildGammaTable();
  2673.  
  2674.     if (!hwnd)
  2675.         return(NULL);
  2676.  
  2677.     i = 0;
  2678.     while (attribList[i] != S3MESA_NONE) {
  2679.         switch (attribList[i]) {
  2680.         case S3MESA_DOUBLEBUFFER:
  2681.             doubleBuffer = GL_TRUE;
  2682.             break;
  2683.         case S3MESA_ALPHA_SIZE:
  2684.             i++;
  2685.             alphaBuffer = attribList[i] > 0;
  2686.             break;
  2687.         case S3MESA_DEPTH_SIZE:
  2688.             i++;
  2689.             depthSize = attribList[i];
  2690.             break;
  2691.         case S3MESA_STENCIL_SIZE:
  2692.             i++;
  2693.             stencilSize = attribList[i];
  2694.             break;
  2695.         case S3MESA_ACCUM_SIZE:
  2696.             i++;
  2697.             accumSize = attribList[i];
  2698.             break;
  2699.         default:
  2700.             return NULL;
  2701.         }
  2702.         i++;
  2703.     }
  2704.  
  2705.  
  2706. #ifdef DEBUG_INIT
  2707.     fprintf(stderr, "S3MESA: s3ctxCreateContext()\n");
  2708. #endif
  2709.  
  2710.     if (!s3mesa_context_count)
  2711.         s3MesaFundamentalInit(hwnd);
  2712.  
  2713.     s3ctx = (s3MesaContext) malloc(sizeof(struct s3_mesa_context));
  2714.     if(!s3ctx)
  2715.         return NULL;
  2716.     memset(s3ctx, 0, sizeof(struct s3_mesa_context));
  2717.     s3ctx->hwnd = hwnd;
  2718.  
  2719.  
  2720.     /* Before allocating any surfaces, should probably clear all texture caches in
  2721.      * all contexts, to give a better chance of it working by defragging VRAM */
  2722.  
  2723.  
  2724. #if USE_FULLSCREEN
  2725.     /* THIS WILL PROBABLY BREAK UNDER MULTIPLE CONTEXTS */
  2726.  
  2727. #ifdef DEBUG_INIT
  2728.     fprintf(stderr, "Initialising for fullscreen\n");
  2729. #endif
  2730.  
  2731.     s3ctx->fullscreen = 1;
  2732.  
  2733.     if ((result = IDirectDraw_SetCooperativeLevel(  gpDD, hwnd,
  2734.                                                     DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN | DDSCL_NOWINDOWCHANGES)) != DD_OK) {
  2735.         fprintf(stderr, "Failed to set cooperative level %x (%d), hwnd %x\n", result, result&0xffff, hwnd);
  2736.         CleanExit(1);
  2737.     }
  2738.  
  2739.     if ((result = IDirectDraw_SetDisplayMode(gpDD, width, height, 16)) != DD_OK) {
  2740.         fprintf(stderr, "Failed to set display mode %x (%d), hwnd %x\n", result, result&0xffff, hwnd);
  2741.         CleanExit(1);
  2742.     }
  2743.  
  2744.     if ((result = DDSetupFullscreenSurfaces(&s3ctx->front_surface, &s3ctx->back_surface)) != DD_OK) {
  2745.         fprintf(stderr, "Failed to create surfaces %x (%d), hwnd %x\n", result, result&0xffff, hwnd);
  2746.         CleanExit(1);
  2747.     }
  2748. #else        // USE_FULLSCREEN
  2749.  
  2750. #ifdef DEBUG_INIT
  2751.     fprintf(stderr, "Initialising for windowed operation\n");
  2752. #endif
  2753.  
  2754.     /* Non-fullscreen setup */
  2755.     s3ctx->fullscreen = 0;
  2756.  
  2757.  
  2758.     GetWindowRect(hwnd, &rect);
  2759.     width = rect.right - rect.left;
  2760.     height = rect.bottom - rect.top;
  2761.  
  2762.     /* Crowbar values in case (for example) window is not visible... in which
  2763.      * case some strange things happen - this fixes it */
  2764.     if (!width) width = 640;
  2765.     if (!height) height = 480;
  2766.  
  2767.     /* This uses the normal Windows front surface we've already picked up */
  2768.     s3ctx->front_surface = front_surface;
  2769.  
  2770.     /* Create a back buffer specifically for this context */
  2771.     if ((result = DDSetupBackSurface(&s3ctx->back_surface, width, height)) != DD_OK) {
  2772. #ifndef S3_SILENT
  2773.         fprintf(stderr, "Failed to create back surface %x (%d), hwnd %x\n", result, result&0xffff, hwnd);
  2774. #endif
  2775.         return(NULL);
  2776.     }
  2777.  
  2778.     /* Non-fullscreen needs a clipper object attached to primary surface */
  2779.     if (IDirectDraw_CreateClipper(gpDD, 0, &s3ctx->clipper, NULL) != DD_OK) {
  2780. #ifndef S3_SILENT
  2781.         fprintf(stderr, "Failed to create clipper %x (%d), hwnd %x\n", result, result&0xffff, hwnd);
  2782. #endif
  2783.         IDirectDrawSurface_Release(s3ctx->back_surface);
  2784.         return(NULL);
  2785.     }
  2786.     if (IDirectDrawClipper_SetHWnd(s3ctx->clipper, 0, hwnd) != DD_OK) {
  2787. #ifndef S3_SILENT
  2788.         fprintf(stderr, "Failed to set clipper %x (%d), hwnd %x\n", result, result&0xffff, hwnd);
  2789. #endif
  2790.         IDirectDrawSurface_Release(s3ctx->back_surface);
  2791.         IDirectDrawClipper_Release(s3ctx->clipper);
  2792.         return(NULL);
  2793.     }
  2794.     if (IDirectDrawSurface_SetClipper(s3ctx->front_surface, s3ctx->clipper) != DD_OK) {
  2795. #ifndef S3_SILENT
  2796.         fprintf(stderr, "Failed to bind clipper %x (%d), hwnd %x\n", result, result&0xffff, hwnd);
  2797. #endif
  2798.         IDirectDrawSurface_Release(s3ctx->back_surface);
  2799.         IDirectDrawClipper_Release(s3ctx->clipper);
  2800.         return(NULL);
  2801.     }
  2802. #endif
  2803.  
  2804.  
  2805. #ifdef DEBUG_INIT
  2806.     fprintf(stderr, "Screen mode OK\n");
  2807. #endif
  2808.  
  2809.     s3ctx->width            = width;
  2810.     s3ctx->height            = height;
  2811.     s3ctx->double_buffer    = doubleBuffer;
  2812.     s3ctx->color            = PACKEDCOLOR(255,255,255,255);
  2813.     s3ctx->clearc            = 0;
  2814.     s3ctx->cleara            = 0;
  2815.     s3ctx->wscale            = 65535.0f / 100.0f;
  2816.     s3ctx->currenttex        = 0;
  2817.     s3ctx->renderdisabled    = 0;
  2818.  
  2819.     if (doubleBuffer)
  2820.         s3ctx->current_buffer = GL_BACK;
  2821.     else
  2822.         s3ctx->current_buffer = GL_FRONT;
  2823.  
  2824.     s3f->S3DTK_GetState(s3f, S3DTK_VIDEOMEMORYADDRESS, (ULONG) &s3ctx->vram_base);
  2825.     s3ctx->vram_base = LinearToPhysical(s3ctx->vram_base);
  2826.     s3f->S3DTK_SetState(s3f, S3DTK_RENDERINGTYPE, S3DTK_GOURAUD);
  2827.     s3f->S3DTK_SetState(s3f, S3DTK_TEXBLENDINGMODE, S3DTK_TEXMODULATE);
  2828.  
  2829.     s3ctx->s3_draw.sfWidth = width;
  2830.     s3ctx->s3_draw.sfHeight = height;
  2831.     if (s3ctx->fullscreen) 
  2832.     s3ctx->s3_draw.sfFormat = S3DTK_VIDEORGB15 | S3DTK_VIDEO;
  2833.     else
  2834.     {
  2835.         memset(&ddsd,0,sizeof(ddsd));
  2836.         ddsd.dwSize=sizeof(ddsd);
  2837.         IDirectDrawSurface2_GetSurfaceDesc(s3ctx->back_surface,&ddsd);
  2838.         if(ddsd.lPitch > ddsd.dwWidth*2) //Assume 24-bit - Not exactly right - lazy bum
  2839.         {
  2840.             fprintf(stderr,"Using 24-bit depth\n");
  2841.             s3ctx->s3_draw.sfFormat = S3DTK_VIDEORGB24 | S3DTK_VIDEO;
  2842.         }
  2843.         else
  2844.         {
  2845.             fprintf(stderr,"pitch = %d width=%d\n",ddsd.lPitch,ddsd.dwWidth);
  2846.             s3ctx->s3_draw.sfFormat = S3DTK_VIDEORGB15 | S3DTK_VIDEO;
  2847.         }
  2848.     }
  2849.  
  2850.     s3ctx->s3_z.sfWidth = width;
  2851.     s3ctx->s3_z.sfHeight = height;
  2852.  
  2853.     s3ctx->s3_z.sfFormat = S3DTK_Z16 | S3DTK_VIDEO;
  2854.  
  2855.     s3ctx->window_width = width;
  2856.     s3ctx->window_height = height;
  2857.     if (s3ctx->fullscreen) {
  2858.         s3ctx->screen_width = width;
  2859.         s3ctx->screen_height = height;
  2860.     } else {
  2861.         GetWindowRect(GetDesktopWindow(), &rect);
  2862.         s3ctx->screen_width = rect.right - rect.left;
  2863.         s3ctx->screen_height = rect.bottom - rect.top;
  2864.     }
  2865.     s3rect.left = 0;
  2866.     s3rect.right = width;
  2867.     s3rect.top = 0;
  2868.     s3rect.bottom = height;
  2869.     s3f->S3DTK_SetState(s3f, S3DTK_CLIPPING_AREA, (ULONG) &s3rect);
  2870.  
  2871.     SetRenderAddress(s3ctx);
  2872.  
  2873.     /* Texture cache */
  2874.     s3ctx->texture_cache_head = s3ctx->texture_cache_tail = 0;
  2875.  
  2876. #ifdef DEBUG_INIT
  2877.     fprintf(stderr, "Setstates done\n");
  2878. #endif
  2879.  
  2880.     /* Build the GL contexts to go with ours */
  2881.  
  2882.  
  2883.     s3ctx->gl_vis = gl_create_visual(    GL_TRUE,     /* RGB mode */
  2884.                                         alphaBuffer,
  2885.                                         doubleBuffer,
  2886.                                         depthSize,   /* depth_size */
  2887.                                         stencilSize, /* stencil_size */
  2888.                                         accumSize,   /* accum_size */
  2889.                                         0,           /* index bits */
  2890.                                         255.0,       /* color scales */
  2891.                                         255.0,
  2892.                                         255.0,
  2893.                                         255.0,
  2894.                                         8, 8, 8, 0);
  2895.     if (!s3ctx->gl_vis) {
  2896. #ifndef S3_SILENT
  2897.         fprintf(stderr, "Couldn't create visual\n");
  2898. #endif
  2899.         IDirectDrawSurface_Release(s3ctx->back_surface);
  2900.         IDirectDrawClipper_Release(s3ctx->clipper);
  2901.         return(NULL);
  2902.     }
  2903.  
  2904.     s3ctx->gl_ctx = gl_create_context(    s3ctx->gl_vis,
  2905.                                         NULL,  /* share list context */
  2906.                                         (void *) s3ctx);
  2907.     if (!s3ctx->gl_ctx) {
  2908. #ifndef S3_SILENT
  2909.         fprintf(stderr, "Couldn't create OpenGL context\n");
  2910. #endif
  2911.         IDirectDrawSurface_Release(s3ctx->back_surface);
  2912.         IDirectDrawClipper_Release(s3ctx->clipper);
  2913.         return(NULL);
  2914.     }
  2915.  
  2916.     s3ctx->gl_buffer = gl_create_framebuffer(s3ctx->gl_vis);
  2917.     if (!s3ctx->gl_buffer) {
  2918. #ifndef S3_SILENT
  2919.         fprintf(stderr, "Couldn't create framebuffer\n");
  2920. #endif
  2921.         IDirectDrawSurface_Release(s3ctx->back_surface);
  2922.         IDirectDrawClipper_Release(s3ctx->clipper);
  2923.         return(NULL);
  2924.     }
  2925.  
  2926. #ifdef DEBUG_INIT
  2927.     fprintf(stderr, "GL ready\n");
  2928. #endif
  2929.  
  2930.     BuildDispatchTable(s3ctx->gl_ctx);
  2931.  
  2932.     s3mesa_context_count++;
  2933.  
  2934.     return s3ctx;
  2935. }
  2936.  
  2937.  
  2938. /*
  2939.  * Destroy the given S3/Mesa context.
  2940.  */
  2941. void s3MesaDestroyContext(s3MesaContext ctx)
  2942. {
  2943. #ifdef DEBUG_INIT
  2944.     fprintf(stderr, "S3MESA: s3MesaDestroyContext()\n");
  2945. #endif
  2946.  
  2947.     if (ctx) {
  2948.         if (ctx->clipper)
  2949.             IDirectDrawClipper_Release(ctx->clipper);
  2950.         if (ctx->z_surface)
  2951.             IDirectDrawSurface_Release(ctx->z_surface);
  2952.         if (ctx->back_surface)
  2953.             IDirectDrawSurface_Release(ctx->back_surface);
  2954.  
  2955.         gl_destroy_visual(ctx->gl_vis);
  2956.         gl_destroy_context(ctx->gl_ctx);
  2957.         gl_destroy_framebuffer(ctx->gl_buffer);
  2958.  
  2959.         s3mesa_context_count--;
  2960.  
  2961.         if (!s3mesa_context_count)
  2962.             s3MesaFundamentalShutdown();
  2963.  
  2964.         free(ctx);
  2965.     }
  2966.  
  2967.     if (ctx == Currents3MesaCtx)
  2968.         Currents3MesaCtx = NULL;
  2969. }
  2970.  
  2971. /*
  2972.  * Make the specified S3/Mesa context the current one.
  2973.  */
  2974. void s3MesaMakeCurrent(s3MesaContext ctx)
  2975. {
  2976. #ifdef DEBUG_GL
  2977.     fprintf(stderr, "S3MESA: s3MesaMakeCurrent()\n");
  2978. #endif
  2979.  
  2980.     if (!ctx) {
  2981.         gl_make_current(NULL,NULL);
  2982.         Currents3MesaCtx=NULL;
  2983.  
  2984.         return;
  2985.     }
  2986.  
  2987.     Currents3MesaCtx = ctx;
  2988.  
  2989.     gl_make_current(ctx->gl_ctx,ctx->gl_buffer);
  2990.  
  2991.     SetRenderState(ctx->gl_ctx);
  2992.     gl_Viewport(ctx->gl_ctx,0,0,ctx->width,ctx->height);
  2993. }
  2994.  
  2995.  
  2996. /*
  2997.  * Swap front/back buffers for current context if double buffered.
  2998.  */
  2999. void s3MesaSwapBuffers(void)
  3000. {
  3001.     s3MesaContext s3ctx = Currents3MesaCtx;
  3002.  
  3003. #if defined(DEBUG_GL) || defined(DEBUG_SURFACES)
  3004.     fprintf(stderr, "S3MESA: s3MesaSwapBuffers()\n");
  3005. #endif
  3006.  
  3007.     if (s3ctx->double_buffer)
  3008.         DDDoubleBuffer( s3ctx->hwnd, s3ctx->front_surface, s3ctx->back_surface,
  3009.                         s3ctx->width, s3ctx->height);
  3010.  
  3011.     SetRenderAddress(s3ctx);
  3012. }
  3013.  
  3014.  
  3015. /*
  3016.  * Called whenever a WM_MOVE message is received
  3017.  */
  3018. void s3MesaMoveWindow(s3MesaContext s3ctx, int x, int y)
  3019. {
  3020. #if USE_FULLSCREEN
  3021. #else
  3022. #endif
  3023. }
  3024.  
  3025. /*
  3026.  * Called whenever a WM_SIZE message is received
  3027.  */
  3028. void s3MesaResizeWindow(s3MesaContext s3ctx, int w, int h)
  3029. {
  3030. #if USE_FULLSCREEN
  3031. #else
  3032.     int reallocate_back = 0, reallocate_z = 0;
  3033.  
  3034.     w = (w+3) & ~3;
  3035.  
  3036. #ifdef DEBUG_SURFACES
  3037.     fprintf(stderr, "Resizing to %d, %d\n", w, h);
  3038. #endif
  3039.  
  3040.     /* Have to resize back and z surfaces: first, free everything but the front
  3041.      * surface, to clear video memory */
  3042.     if (s3ctx->back_surface) {
  3043.         IDirectDrawSurface_Release(s3ctx->back_surface);
  3044.         reallocate_back = 1;
  3045.         s3ctx->back_surface = NULL;
  3046.     }
  3047.     if (s3ctx->z_surface) {
  3048.         IDirectDrawSurface_Release(s3ctx->z_surface);
  3049.         reallocate_z = 1;
  3050.         s3ctx->z_surface = NULL;
  3051.     }
  3052.     ClearTextureCache(s3ctx);
  3053.  
  3054.     /* Mark as resized in the S3 surfaces */
  3055.     s3ctx->s3_draw.sfWidth = w;
  3056.     s3ctx->s3_draw.sfHeight = h;
  3057.     s3ctx->s3_z.sfWidth = w;
  3058.     s3ctx->s3_z.sfHeight = h;
  3059.     s3ctx->window_width = w;
  3060.     s3ctx->window_height = h;
  3061.  
  3062.     /* Mark as resized in the context */
  3063.     s3ctx->width = w;
  3064.     s3ctx->height = h;
  3065.  
  3066.     /* Reallocate if there was one there before */
  3067.     s3ctx->renderdisabled &= ~1;
  3068.     if (reallocate_back) {
  3069.         if (DDSetupBackSurface(&s3ctx->back_surface, w, h) != DD_OK) {
  3070. #ifndef S3_SILENT
  3071.             fprintf(stderr, "Failed to resize back buffer\n");
  3072. #endif
  3073.             s3ctx->renderdisabled |= 1;
  3074.             BuildDispatchTable(s3ctx->gl_ctx);
  3075.             return;
  3076.         }
  3077.     }
  3078.     if (reallocate_z) {
  3079.         if (DDSetupZSurface(&s3ctx->z_surface, w, h) != DD_OK) {
  3080. #ifndef S3_SILENT
  3081.             fprintf(stderr, "Failed to resize Z buffer\n");
  3082. #endif
  3083.             s3ctx->renderdisabled |= 1;
  3084.             BuildDispatchTable(s3ctx->gl_ctx);
  3085.             return;
  3086.         }
  3087.     }
  3088.  
  3089.     if (s3ctx == Currents3MesaCtx)
  3090.         SetRenderAddress(s3ctx);
  3091. #endif
  3092. }
  3093.  
  3094.  
  3095.  
  3096. #endif  /* S3 */
  3097.